最近我和我的朋友们正在对不同的编程语言进行基准测试。当我最近学习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编写的那些)。
问题是 - 如何让它跑得更快?
答案 0 :(得分:10)
首先,执行一些简单计算并将每个结果写入文件的基准仅对测试IO系统有用。他们根本没有说计算效率,因为大部分时间花在文件访问上。如果你想比较语言用于计算事物的速度,你需要做一些处理器密集型的事情(例如,将所有这些平方值相加),然后只输出那个结果。
如果你真的想要比较文件输出性能,Haskell中的主要问题是它的String
类型。它是一个简单的字符列表,方便用手进行简单的文本操作,但标准任务的开销却很荒谬。要获得更快的效果,请使用bytestrings或Text
。具体而言,您需要更快的替代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版本。
你应该记住,这段代码仍在使用字符串,并且只有concat
和hPutStrLn
使用ByteString,还有额外的开销(将字符串打包成ByteString)。