はねたブログ

はねたのブログです. github:@ecofighter

tinysegmenterをHaskellに移植したらJulia,Goより速くなりました

Haskellで日本語を分かち書きしたいなあと思ってライブラリを探していたらtinysegmenterという面白そうなものを見つけました.
TinySegmenter:Javascriptだけで書かれたコンパクトな分かち書きソフトウェア
TinySegmenter.jlをGoと比較して負けたと思ったら若者が最適化してくれた

元はJavaScriptのライブラリで,色々な言語に移植されているようです.
せっかくなのでHaskellでも実装してみました.

https://github.com/ecofighter/tinysegmenter-hs
ソースコードはここです. 最適化は全くしていないので,指導してくれる方がいらっしゃいましたらよろしくお願いします.

とりあえず速いらしいJuliaのものを参考にしましたが,少し変えてindexingでのチェックではなく 入力を前から消費していくようになっています.

とりあえず手元の環境でベンチマークを取ったところ結果は以下のようになりました.

f:id:haneta_ecose:20190715235615p:plain
benchmark result
それぞれghc-8.6.5 -O2 -fllvm,julia v1.1.1, go 1.12.7, rustc 1.38.0-nightly (4bb6b4a5e 2019-07-11)を使っています.

TextでもJuliaと良い勝負で,ByteStringはJuliaと比べても速いです.
しかしByteString版はUTF-8決め打ちで処理しており不正なバイト列だった場合は例外を投げたり最悪Out of Boundsで落ちてしまいます.Go,Juliaはどちらもライブラリの関数を呼んでいるのでその分のハンデはあるでしょう.
しかしぶっちゃけバリデーションとかその辺はIO側でやるべきことだとは思うので,このままでいい気はします.

ごちゃごちゃ言いましたが感想としては,Haskellだと雑にStateモナドにレコードを放り込むだけでアクションを分割して書けて嬉しいし,それを結構最適化してくれるのでGHCは凄いなあと思いました.

あとこれはやってから気付いたのですが,動かないと思っていたHackageにあるmecabバインディングは依存ライブラリのバージョンを弄るだけでビルドが通ったのでこれをやる意味はありませんでした.
終わりです.