krの日記: Haskellで速いwcを書いてみよう(2)
前のエントリからの続きです。
まずはtanakh氏の跡を追ってみようということで、 氏の書いたHaskell版、C++版、C版のwcの実行速度を、手元のマシンで計測してみます。
まずはHaskell版。使ったコンパイラは、
% ghc --version
The Glorious Glasgow Haskell Compilation System, version 6.6.1
というものです。
早速、氏の「7月27日あたりで書いた全く直截的なコード」とあるものをそのままコピーして、コンパイルしました。 テスト用入力としては、手元にあってそこそこ大きいテキストファイルということで、 /usr/share/doc/en/books/handbook/book.txt(FreeBSD handbook)を喰わせてみました。
……が、いきなり挫折で、Stack space overflowと出て動きません。
実はこの結果は予想していました。読み込んだテキストをすべてメモリに保持して、行数・単語数・文字数をそれぞれ計算しているので、 まあ当然かなと。(ちなみにHaskellは文字列をUnicode文字のリストとして保持するので、そういうことをすると、やたらメモリを食います。)
念のため書いておくと、例えば単語数だけ表示するプログラムだったら、同じように書いてもちゃんと動きます。
-- prog1
main = getContents >>= putStrLn . show . length . words
一応この速度を測っておくと、以下のようでした。(2回目以降のコマンドラインと出力結果は省略)
% time ./prog1 < /usr/share/doc/en/books/handbook/book.txt
323341
0.767u 0.007s 0:00.80 95.0% 345+271k 0+0io 0pf+0w
0.758u 0.016s 0:00.80 95.0% 328+257k 0+0io 0pf+0w
0.772u 0.001s 0:00.80 96.2% 314+246k 0+0io 0pf+0w
0.766u 0.007s 0:00.80 95.0% 331+260k 0+0io 0pf+0w
0.752u 0.022s 0:00.80 96.2% 344+269k 0+0io 0pf+0w
実時間で0.80秒ですね。 一見、ファイルを全部読み込んでいるようにも見えますが、実際には1単語分の文字列を構築しては捨てていくので、最長単語が保持できるメモリさえあれば動きます。遅延評価万歳。
ただし行数と文字数を表示しない点で、今回のお題に合わないので、これはあくまで参考ということで。