さて、私のボックスでは、コンパイルされたCコードのgcc -O3
実行には約21.5秒かかりますが、元のHaskellコードは約56秒かかります。したがって、5倍ではなく、2.5より少し上です。
最初の重要な違いは
mapM_ print [1..100000000]
sを使用します。これは、事前のInteger
チェックが含まれるため少し遅くなり、ボックス化されInt
たsで機能しますが、のShow
インスタンスはボックス化されていないsで機能します。Int
Int#
型署名を追加して、HaskellコードがInt
sで機能するようにします。
mapM_ print [1 :: Int .. 100000000]
時間を47秒に短縮します。これは、Cコードにかかる時間の2倍を少し上回ります。
さて、もう1つの大きな違いは、バイトの連続したバッファを埋めるだけでなくshow
、のリンクリストを生成することです。Char
それも遅いです。
次に、そのリンクされたsのリストを使用して、ハンドルChar
に書き込まれるバイトバッファを埋めます。stdout
したがって、HaskellコードはCコードよりも多くの、そしてより複雑なことを行うので、それがより長くかかることは驚くべきことではありません。
確かに、そのようなものをより直接的に(したがってより速く)出力する簡単な方法があることが望ましいでしょう。ただし、これを処理する適切な方法は、より適切なアルゴリズムを使用することです(Cにも適用されます)。への簡単な変更
putStr . unlines $ map show [0 :: Int .. 100000000]
所要時間はほぼ半分になります。本当に高速にしたい場合は、より高速なI / Oを使用して、アプリケーションの回答ByteString
に示されているように効率的に出力を構築します。