2

次の Groovy コードのスニペットで、予想外のベンチマーク結果が得られました。

class A{
    def n(){
        return 1
    }
}
class B{
    def n(){
        return 2
    }
}
class C{
    def n(){
        return 3
    }
}
class D{
    def n(){
        return 4
    }
}

def bench(loops){
    def a = new A()
    def b = new B()
    def c = new C()
    def d = new D()
    def ret=0
    for(i=0; i<loops; i++){
        ret = ret + getN(a) + getN(b) + getN(c) + getN(d)
    }
    return ret
}

def getN(clazz){
    return clazz.n()
}

コンパイル済みのクラス ファイルを使用し、それを Reflection API で呼び出したと言わざるを得ません。語るべき長い話 (聞かないでください ;)。第一印象として、私は 10 ラウンド + 5 回のウォームアップを 10000 ループで使用しました。(junit-benchmark フレームワーク) 私の JDK は Verison 1.7.0_09 で、Groovy 2.1 を使用しました。このコードは、invokedynamic サポートありとなしで 2 回コンパイルしました。要点は、invokedynamic を使用したベンチマークは、通常のコンパイル済みのものよりもはるかに長い時間がかかったということです。また、フィボナッチ数を使用して他のベンチマークも行いましたが、予想どおりに動作しました (indy は約半分の時間かかりました)。

ここで何が問題なのか誰か知っていますか?

ありがとう。

4

1 に答える 1

1

私はGroovyの専門家ではありませんが、Groovyが「神のクラス」のようなものを作成することをどこかで読んだような印象があります。このクラスには、Groovy ソース コードに表示されるすべてのメソッドが含まれており、サブクラスは特定のメソッドのみをオーバーライドします。このようなクラスを作成すると、動的ルックアップではなく、通常の invokevirtual 呼び出しが可能になります。それが減速の説明かもしれません。

クラスへのメソッドのランタイム インジェクションをいくつか試して、Groovy の静的分析を中断し、コンパイラに動的ルックアップ コードを出力させます。

于 2013-06-04T13:11:54.200 に答える