好的,在我的电脑上,使用gcc -O3
编译的C代码大约需要21.5秒才能运行,而原始的Haskell代码需要大约56秒。因此,不是5的倍数,略高于2.5。
第一个非微不足道的差异在于
mapM_ print [1..100000000]
使用 Integer
会稍微慢一些,因为它需要在前面进行检查,然后使用封装的 Int
,而 Int
的 Show
实例在未封装的 Int#
上完成转换工作。
添加类型签名,以便 Haskell 代码适用于 Int
。
mapM_ print [1 :: Int .. 100000000]
将时间缩短到47秒,略高于C代码所需时间的两倍以上。
另一个重要区别在于show
函数生成一个Char
链表,而不是填充一个连续的字节缓冲区。这也更慢一些。
然后,这个Char
链表被用来填充一个字节缓冲区,然后写入stdout
处理器中。
因此,Haskell代码比C代码做了更多、更复杂的事情,因此它需要更长的时间。
无可否认,希望有一种更简单的方法可以更直接(从而更快地)输出这些内容。然而,正确的处理方式是使用更适合的算法(也适用于C代码)。对以下代码进行简单更改即可:
putStr . unlines $ map show [0 :: Int .. 100000000]
近乎减半了所需时间,如果需要更快的速度,可以使用更快的ByteString
I/O并高效构建输出,就像applicative's answer中所示。
let xs = unlines $ map show [1..100000000] in return ()
。这个代码实现了相同的效果,但是运行速度更快。 - AndrewC