与其他语言相比,简单的数学运算和保存到文件需要花费太多时间

时间:2015-07-14 09:36:55

标签: performance haskell math file-io

最近我和我的朋友们正在对不同的编程语言进行基准测试。当我最近学习Haskell时,我想表明一个函数式语言的表现几乎与C一样好,代码更简单。但下面粘贴的代码,用GHC的-O3选项编译,在我的机器上执行大约1.6秒。 Python和Ruby中的等效脚本执行得更快(这是一个简单的for循环)。

import System.IO

saveLine fh x = hPutStrLn fh $ show x ++ "\t" ++ show (x^2)

main = do
    fh <- openFile "haskell.txt" WriteMode
    mapM (saveLine fh) [1..999999]
    hClose fh

你可以查看codes in other languages here(我只用Python和Ruby编写的那些)。

问题是 - 如何让它跑得更快?

3 个答案:

答案 0 :(得分:10)

首先,执行一些简单计算并将每个结果写入文件的基准仅对测试IO系统有用。他们根本没有说计算效率,因为大部分时间花在文件访问上。如果你想比较语言用于计算事物的速度,你需要做一些处理器密集型的事情(例如,将所有这些平方值相加),然后只输出那个结果。

如果你真的想要比较文件输出性能,Haskell中的主要问题是它的String类型。它是一个简单的字符列表,方便用手进行简单的文本操作,但标准任务的开销却很荒谬。要获得更快的效果,请使用bytestringsText。具体而言,您需要更快的替代show。查看text-format package

答案 1 :(得分:3)

问题是:1)使用ByteString,以及2)将整数值格式化为字符数据(String{-# LANGUAGE OverloadedStrings #-} import System.IO import qualified Data.ByteString.Char8 as BS -- saveLine fh x = hPutStrLn fh $ show x ++ "\t" ++ show (x^2) -- original version -- saveLine fh x = hPutStrLn fh "123456\t123456789012" -- String version saveLine fh x = BS.hPutStrLn fh "123456\t123456789012" -- ByteString version main = do fh <- openFile "haskell.txt" WriteMode mapM_ (saveLine fh) [1..999999] hClose fh )。

original version:   1.6 secs
String version:     0.7 secs
ByteString version: 0.3 secs

我机器上的运行时间是(GHC 7.8.3):

<?php

if(true) {  // your condition in true's  place
?>
    if true your html code here
like <form action="aa.html"></form>
<?php
} else {
?>
    else your html code here
like <form action="bb.html"></form>
<?php 
}
?>

因此,如果可以找到更快的方法将整数值格式化为ByteStrings,则可以显着提高运行时间。

答案 2 :(得分:1)

首先,您应该避免使用 -O3 ,因为它有时会破坏您的代码(即使在gcc中)。坚持 -O2

其次, Haskell字符串为really slow

但是,there are faster alternatives - 对我来说,最简单的就是使用Data.ByteString(little and old tutorial)。

第三,如果你不需要mapM use mapM_的结果 - 它的快得多

最后,这是我的代码版本,使用Data.ByteString:

{-# LANGUAGE OverloadedStrings #-}
--  that line is so You could use "\t" instead of T.pack "\t"

import System.IO
import qualified Data.ByteString.Char8 as T

helperFun x = T.concat [y, "\t", z]
          where
            y = T.pack $ show x
            z = T.pack $ show $ x^2

saveLine fh x = T.hPutStrLn fh $ helperFun x

main = do
    fh <- openFile "haskell.txt" WriteMode
    mapM_ (saveLine fh) [1..999999]
    hClose fh

修改 user5402 在评论中表示并非如此&#34;更快&#34;然后是Strings版本。

你应该记住,这段代码仍在使用字符串,并且只有concathPutStrLn使用ByteString,还有额外的开销(将字符串打包成ByteString)。