HaskellでStringを使う場合とByteStringを使う場合の速度比較

Sun Jun 9 10:13:52 JST 2013 (modified: Sun Oct 1 10:50:27 JST 2017)
views: 1270, keywords:プログラミング,Haskell この記事は最終更新日が7年以上前のものです。

ここ数ヶ月、だれに頼まれたわけでもなく、open usp TukubaiをPython版からHaskell版に置き換える作業をだらだら続けていますが、最近ようやくHaskellを書くのに不自由さを感じなくなってきました。

そうなってくるとスピードのことが気になります。Haskell には文字列を扱う String と、それよりもう少し抽象度の低い ByteString がありますが、スピードは抽象度の低い ByteString の方が速いそうです。しかし、Haskell初心者の脳みそに負担をかけるのは学習速度が遅くなるという個人的な戦略のため、現在リリースされているコマンドでは String を使っていました。しかし、そろそろ挑戦するべきかと。

んで、さっきdelfというコマンド内部で扱う文字列を String から ByteString (Data.ByteString.Lazy.Char8)に変更したので、スピードを計ってみました。delf は、こんなコマンドです。

bsd /home/ueda$ head -n 3 ~/TESTDATA 
   2377 高知県 -9,987,759 2001年1月5日
   2910 鹿児島県 5,689,492 1992年5月6日
   8458 大分県 1,099,824 2010年2月22日
   ###二列目をdelfで除去###
   bsd /home/ueda$ head -n 3 ~/TESTDATA | delf 2
   2377 -9,987,759 2001年1月5日
   2910 5,689,492 1992年5月6日
   8458 1,099,824 2010年2月22日

便利でしょ?え?使いみちが分からない?分かれば便利なんです。

delfが便利かどうかはおいておいて、String版(delf.normal)とByteString版(delf.bs)を作ったので、比較してみます。ByteString 版はココにアップしてあります。

###python版###
   bsd /home/ueda/tmp$ time head -n 100000 ~/TESTDATA | delf 2 > /dev/null
   
   real    0m3.804s
   user    0m3.814s
   sys 0m0.031s
   ###string版###
   bsd /home/ueda/tmp$ time head -n 100000 ~/TESTDATA | ./delf.normal 2 > /dev/null
   
   real    0m1.661s
   user    0m1.627s
   sys 0m0.079s
   ###ByteString版###
   bsd /home/ueda/tmp$ time head -n 100000 ~/TESTDATA | ./delf.bs 2 > /dev/null
   
   real    0m0.773s
   user    0m0.741s
   sys 0m0.083s

おー。二倍以上。

これは仕事用ハイスペックマッシーンでやったらもっと速いに違いない。・・・ということで仕事用のサーバ(CentOS5.9)で try。

[usp@demo1 ueda]$ uname -a
   Linux demo1 2.6.18-308.8.1.el5 #1 SMP Tue May 29 14:57:25 EDT 2012 x86_64 x86_64 x86_64 GNU/Linux
   ###有償ビジネス版###
   [usp@demo1 ueda]$ time head -n 1000000 TESTDATA | delf 2 > /dev/null
   
   real    0m0.448s
   user    0m0.482s
   sys 0m0.085s
   ###String版###
   [usp@demo1 ueda]$ time head -n 1000000 TESTDATA | ./delf.normal 2 > /dev/null
   
   real    0m5.465s
   user    0m5.476s
   sys 0m0.096s
   ###ByteString版###
   [usp@demo1 ueda]$ time head -n 1000000 TESTDATA | ./delf.bs 2 > /dev/null
   
   real    0m13.397s
   user    0m13.406s
   sys 0m0.075s

あれれれれ????遅いやんけ!!!何回やっても遅い。

うーん。終わり。

appendix: 個人メモ

bsdなら一発コンパイルだったのに、CentOS 5.9でコンパイルしようと思ったらめちゃくちゃ叱られたので、以下のようにコンパイル。 なんか遅い原因はここらへんに関係するのか?どうなのか?

[usp@demo1 ueda]$ cat /etc/redhat-release 
   CentOS release 5.9 (Final)
   [root@demo1 ~]# cabal install parsec
   ...
   [usp@demo1 ueda]$ ghc delf.bs.hs 
   [usp@demo1 ueda]$ ghc --make -o delf.normal delf.normal.hs
   Linking delf.normal ...
ノート   このエントリーをはてなブックマークに追加 
 

prev:仲間を見つけた next:Haskellのerror関数が型破りなんだが型破ってない。

やり散らかし一覧

記事いろいろ