Hatena::ブログ(Diary)

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

2012-09-02

GInspector: an object inspector for Groovy

Groovyで書いたオブジェクトインスペクタ。GroovyJavaオブジェクトを捕まえて、変数を覗いたり、メッセージを送ったり、メソッドセレクタを一覧したりすることができる。

なお、捕まえたオブジェクト自身を指す擬変数(的なものとして)は「this」ではなく、「self」または「_this」を使用している。メッセージ送信(画面下部のテキスト領域で指揮を評価)の際は注意すること。

https://github.com/kaminami/GInspector

f:id:kaminami:20120902212855p:image


EclipseRCPを使用したアプリ副産物で、Groovy標準のGroovyConsoleに不満があったので自作SWTを使用しているのは、EclipseRCPの勉強用でもあったため。

VisualWorks SmalltalkのInspectorを横目に見ながら作成した。


これを、EclipseIntelliJの、デバッガビューの変数リストから起動できると開発効率がグッと上がるはずなのだが、JDI(Java Debug Interface)経由でプロキシ越しにうまくやる方法に辿り着けていない。

2011-05-29

Goist速度計測

形態素解析エンジンGoistの速度を計測した。

以前行ったIgoの結果を含めて簡単に比較する。


環境



測定内容


結果

実行時間
Java(Igo)VW(Igo)VW(Goist)CogVM(Goist)SqueakVM(Goist)
834222926393582 (2回目)
4272 (初回)
27362

単位ミリ


実行時間
Java(Igo)VW(Igo)VW(Goist)CogVM(Goist)SqueakVM(Goist)
12.673.164.29 (2回目)
5.12 (初回)
32.8
0.320.8411.36 (2回目)
1.62 (初回)
10.37
0.230.620.741 (2回目)
1.19 (初回)
7.64

同じロジックで解を出しているのだが、VW(Igo)に比べてVW(Goist)は少々遅い。これは、わかりやすさ優先で冗長に書いた分、辞書構造が変わっていたり、メソッド呼び出しが増えるなどしているので想定通り。まずまず。

CogVMの性能がVisualWorksVMの性能に迫っていて驚かされた。まぁ同じ人が作っているわけだが。SqueakUIフレームワークであるMorphicが絡むと、そこにCPUパワーが取られてしまいがちだが、Webアプリプラットフォームとしてなら、かなりやれそう。ただ、IO周りが遅いので、そちらに引っ張られるかもしれない。

素のSqueakVMにはそろそろ引退かな。

辞書の読み込み時間については、最初に一度読み込んだ後はそれを使いまわすことを想定しているため、重視していない。概ね、Java(Igo)は一瞬、VW(Igo)は7秒、VW(Goist)は15秒、CogVM(Goist)は30秒、SqueakVM(Goist)は75秒程度で、Javaの速さが際立つ。というよりはSmalltalk陣営が遅い。Ruby(Igo)も3秒程度であった。

(追記)

実装が悪かった。VW(Goist)は4秒、CogVM(Goist)は10秒程度まで縮められた。それでもまだJavaRubyが速いが、際立って遅いというわけではないと思われる。


おまけ

CogVMの場合の、各回の結果を載せる。

JITが効いている様子が窺える。

"Squeak-CogVM(Goist) 初回"
6422 milliseconds
4355 milliseconds
4094 milliseconds
3947 milliseconds
4045 milliseconds
4114 milliseconds
4176 milliseconds
4226 milliseconds
3459 milliseconds
3883 milliseconds
Average: 4272 milliseconds
"Squeak-CogVM(Goist) 2回目"
3358 milliseconds
3391 milliseconds
3931 milliseconds
3395 milliseconds
3832 milliseconds
3373 milliseconds
3869 milliseconds
3381 milliseconds
3916 milliseconds
3375 milliseconds
Average: 3582 milliseconds

使用コード

VisualWorks Smalltalk
dictionaryDirectoryPath := 'C:\ipadic-test'.
dictionary := GDictionary from: dictionaryDirectoryPath.
tagger := dictionary newTagger.
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'. 
Squeak Smalltalk
dictionaryDirectoryPath := 'C:\ipadic-squeak-test'.
dictionary := GDictionary from: dictionaryDirectoryPath.
tagger := dictionary newTagger.
fs := FileStream readOnlyFileNamed: 'c:\temp\igo\kokoro.txt'.
contents := fs contents.
fs close.
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'. 

2011-05-24

文字列ソート順の相違

VisualWorks7.7.1の文字列ソート結果が自分の想定と異なっていて、結構な時間を奪われたのでココに記録。

VisualWorksの文字列比較のポリシーが、世間一般から外れているんだと思う。


VisualWorks
#('しょ' 'しよう' 'しょう' 'しよ') asSortedCollection
"==> SortedCollection ('しょ' 'しよ' 'しょう' 'しよう')"
Squeak
#('しょ' 'しよう' 'しょう' 'しよ') asSortedCollection
"==> a SortedCollection('しょ' 'しょう' 'しよ' 'しよう')"
Java
import java.util.ArrayList;

public class SortTest {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        list.add("しょ");
        list.add("しよう");
        list.add("しょう");
        list.add("しよ");
        java.util.Collections.sort(list);
        System.out.println(list);
    }
}

// [しょ, しょう, しよ, しよう]

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")