Hatena::Groupjavascript

JavaScriptで遊ぶよ

 | 

2010-11-16

TinySegmenter を速くしてみる

14:55

存在は知ってたんだけど、初めて使ってみた。

試しに200文字ぐらいのテキストを1000回分かち書きしてみたら、3秒ぐらいかかった。

なんでこんなに時間かかるんだろうと思って、とりあえず this をなくしたり同じ計算を何度もしないようにしたんだけど、これでもまだだいぶ遅かった。

そこでまた考えてみたら、↓こんなふうに、各繰り返しごとに合計42回もハッシュ検索してる部分があって、それをなんとか速くできないかと考えた。1000ループ*200文字*42回=840万回なので馬鹿に出来ない。

    for (var i = 4, m = seg.length - 3; i < m; ++i) {
      var score = BIAS__ +
        (UP1__[p1] || 0) +
        (UP2__[p2] || 0) +
        (UP3__[p3] || 0) +
        (BP1__[p1 + p2] || 0) +
        (BP2__[p2 + p3] || 0) +
        (UW1__[w1] || 0) +
        (UW2__[w2] || 0) +
        (UW3__[w3] || 0) +
        (UW4__[w4] || 0) +
        (UW5__[w5] || 0) +
        (UW6__[w6] || 0) +

TinySegmenter では、各文字を漢字、数字、ひらがな、カタカナ、などに分けて H M I K などと記号をふり、それの組み合わせでハッシュ検索して点数を加算してる部分がある。("HI":626 など)

この文字を数値にしてみたらどうかということで、H を 2、I を 3、HI は 32 などに置き換えてみた


これがかなり良かったので、次に、文字の種類ではなくて文字そのもので点数付けしてる部分("いう":1743, "いっ":-2055 など)も数値にすることにした。

ちょっと面倒だけど、とりあえず各文字を Unicode の順番に直して(charCodeAt)、2文字目以降は100000ずつ繰り上がることにする。(BMP 上 \u0000~\uFFFF = 65535 のどれが来てもいいように)

最終的にはこんな感じになった。


ベンチマーク

なんか↑だとオリジナルと最適化版で結果が違うけど、手元ではちゃんとあってる。どういうことかわからない。「Unicode(|ユニコード|)」の "e" と "(" の間に分かれ目が入るの(最適化版の挙動)が正しい。

うちではこんな結果だった。単位はms。

オリジナル普通の最適化キーを数値に(1)キーを数値に(2)
Firefox6067311025653371
Opera4382185110321669
Chrome4140252814781217

Chrome 以外の2つは4番目より3番目のほうが速かった。これはどういうことだろう。もしかしたら、ハッシュのキーが数値だと検索が速いというのは小さい数値だけで、215160004900066 のようなキーだったら文字列と同じ扱いなのかもしれない。

とりあえず自分は Chrome で使うことを想定してるので深入りしないでおく。


あと TinySegmenter の漢字判定は [一-龠々〆ヵヶ] なんだけどそれだと云々。

トラックバック - http://javascript.g.hatena.ne.jp/edvakf/20101116
 |