Hatena::ブログ(Diary)

駄文生産所 このページをアンテナに追加 RSSフィード

2011-05-09

形態素解析で速度比較

IgoのVisualWorks版がどの程度やれるのか、興味があったので測ってみた。

JavaRubyVisualWorks比較VisualWorksはIgoとDLL/CCを使用したMeCabバインディング


環境


測定内容


結果

 JavaVW(Igo)VW(MeCab)Ruby
100行410292970
300行14356819442
1000行53170254251818
全て(10731行)83422292991待てません

単位ミリ


結果としては、Java > VisualWorks(Igo) > VisualWorks(MeCab) >>> RubyJava : VisualWorks : Ruby = 1 : 3 : 1000 程度。ちょっと異常な感。

基本的には同じロジック使用しているはずなので、Rubyの使い方を間違えたのかと思う程に遅い。100行〜1000行の間で処理時間が約100倍になっているので、テキストをすべてパースし終えるには、、、最小で見積もっても7時間はかかる。

JavaVisualWorksが共に内部では文字を2バイト固定で保持しているのに対して、RubyUTF-8なのが問題なのだと推測する。UTF-16やUTF-32、UCS-2を指定すれば劇的に改善するかもしれない。

VisualWorksMeCabバインディングの方が遅かった。Java版のIgoとMeCabの速度はそう変わらないそうなので、DLL/CCオーバーヘッドがバカにならないようだ。

IgoのVisualWorks版は、2000文字で10ミリ秒、20000文字で200ミリ秒と考えると、大抵の場面で使用に耐えるレベルだと思う。


使用コード

Java
package net.reduls.igo;

import java.io.FileReader;

public class Main {
    public static void main(String[] args) {
        try {
            Tagger tagger = new Tagger( "C:\\temp\\igo\\ipadic" );

            FileReader in = new FileReader("C:\\temp\\igo\\kokoro.txt");
            StringBuilder sb = new StringBuilder();
            int c;
            while ((c = in.read()) != -1) {
                sb.append((char)c);
            }
            in.close();
            String contents = sb.toString();
            
            long sum = 0;
            for(int i = 0; i < 10; i++) {
                long start = System.currentTimeMillis();
                tagger.parse(contents);
                long timeToRun = System.currentTimeMillis() - start;
            
                sum = sum + timeToRun;
                System.out.println(timeToRun + " milliseconds");
            }
            System.out.println("Average: " + (sum / 10) + " milliseconds");
            
        } catch (Exception e) {
            // noop
        } 
    }
}
VisualWorks Smalltalk
"Igo"
| dicDirPath tagger contents sum |
dicDirPath := 'C:\temp\igo\ipadic'.
tagger := IgoTagger dicDir: dicDirPath.
contents := ('c:\temp\igo\kokoro.txt' asFilename withEncoding: #'utf-8') readStream contents.
sum := 0.
10 timesRepeat: [
    | timeToRun |
    timeToRun := Time millisecondsToRun: [tagger parse: contents].
    
    sum := sum + timeToRun.
    Transcript cr; show: timeToRun printString , ' milliseconds'.
].
Transcript cr; show: 'Average: ' , (sum // 10) printString , ' milliseconds'.
"MeCab"
| tagger contents sum |
tagger := MeCabTagger new.
contents := ('c:\temp\igo\kokoro.txt' asFilename withEncoding: #'utf-8') readStream contents.
sum := 0.
10 timesRepeat: [
    | timeToRun |
    timeToRun := Time millisecondsToRun: [tagger parse: contents].
    
    sum := sum + timeToRun.
    Transcript cr; show: timeToRun printString , ' milliseconds'.
].
Transcript cr; show: 'Average: ' , (sum // 10) printString , ' milliseconds'.

Ruby
require 'rubygems'
require 'igo-ruby'

tagger = Igo::Tagger.new("c:/temp/igo/ipadic")

f = open("c:/temp/igo/kokoro.txt")
contents = f.read
f.close

sum = 0
10.times{
    start = Time.now
    tagger.parse(contents)
    timeToRun = (Time.now - start) * 1000
    
    sum = sum + timeToRun
    puts("#{timeToRun} milliseconds")
}
puts("Average: #{sum / 10} milliseconds")

2009-05-15

MeCab for VisualWorks Ver.001

形態素解析エンジンMeCab(http://mecab.sourceforge.net/)をCincom Smalltalk VisualWorks から使用するためのラッパーライブラリ

日本語形態素解析、わかち書き、読み仮名の取得などが行えます。

MeCabの提供するフル機能はサポートできていませんが、ちょっと形態素解析を試してみたい、というような用途には十分でしょう。


"サンプルコード"

"とりあえず形態素解析"
"出力は次の順:表層形\t品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用形,活用型,原形,読み,発音"
MeCabTagger parse: '庭には二羽鶏がいる'
"=>
'庭	名詞,一般,*,*,*,*,庭,ニワ,ニワ
に	助詞,格助詞,一般,*,*,*,に,ニ,ニ
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
二	名詞,数,*,*,*,*,二,ニ,ニ
羽	名詞,接尾,助数詞,*,*,*,羽,ワ,ワ
鶏	名詞,一般,*,*,*,*,鶏,ニワトリ,ニワトリ
が	助詞,格助詞,一般,*,*,*,が,ガ,ガ
いる	動詞,自立,*,*,一段,基本形,いる,イル,イル
EOS'"


"表層語、読み、発音を抽出"
| str tagger node ws |
str := '東京特許許可局でバスガス爆発'.
tagger := MeCabTagger new.
node := tagger parseToNode: str.
ws := WriteStream on: String new.
[node hasNext]
    whileTrue:
        [| out |
        out := '<1s><t><2s><t><3s><n>' 
                    expandMacrosWith: node surface 
                    with: node yomi 
                    with: node pronounce.
        ws nextPutAll: out.
        node := node next].
^ ws contents
"=>
'東京	トウキョウ	トーキョー
特許	トッキョ	トッキョ
許可	キョカ	キョカ
局	キョク	キョク
で	デ	デ
バス	バス	バス
ガス	ガス	ガス
爆発	バクハツ	バクハツ'"


"わかち書き"
MeCabTagger wakati: '庭には二羽鶏がいる'
"=> '庭 に は 二 羽 鶏 が いる'"

'庭には二羽鶏がいる' wakati
"=> '庭 に は 二 羽 鶏 が いる'"


"読み"
MeCabTagger yomi: '庭には二羽鶏がいる'
"=> 'ニワニワニハニワニワトリガイル'"

'庭には二羽鶏がいる' yomi
"=> 'ニワニワニハニワニワトリガイル'"