Frage

Ich habe einige Java-Code, der bitweise Operationen auf einem BitSet führt. Ich habe eine Liste von Operationen und „interpretieren“, um sie über sie durch Looping, aber es ist mir wichtig, dass ich diese Operationen so schnell wie möglich durchführen können, so habe ich versucht, dynamisch-Code zu generieren, um sie anzuwenden. Ich erzeugen Java-Quellcode, die Operationen durchführen und eine Klasse zu kompilieren, diese Vorgänge mit Javassist implementieren.

Leider ist mein dynamisch generierten Code läuft langsamer als der interpretierten Code. Es scheint, dass dies, weil HotSpot wird, um den interpretierten Code zu optimieren, aber nicht den kompilierten Code zu optimieren: Nachdem ich es ein paar tausend mal laufen, mein interpretierten Code läuft doppelt so schnell, wie es anfangs tat, aber mein kompilierten Code zeigt keine Beschleunigung. In Übereinstimmung mit dieser Hypothese, mein interpretierten Code ist zunächst langsamer als der kompilierten Code, ist aber letztendlich schneller.

Ich bin mir nicht sicher, warum dies geschieht. Meine Vermutung ist, dass vielleicht Javassist verwendet einen Klassenlader, der Klassen HotSpot nicht berührt. Aber ich bin kein Experte auf dem Laden von Klassen in Java, so dass ich bin mir nicht sicher, ob dies eine vernünftige Vermutung ist, oder wie man über sie zu testen. Hier ist, wie ich das Erstellen und die Klasse mit Javassist:

ClassPool pool = ClassPool.getDefault();
CtClass tClass = pool.makeClass("foo");

// foo implements MyInterface, with one method
tClass.addInterface(pool.get(MyInterface.class.getName()));

// Get the source for the method and add it
CtMethod tMethod = CtNewMethod.make(getSource(), tClass);
tClass.addMethod(tMethod);

// finally, compile and load the class
return (MyInterface)tClass.toClass().newInstance();

Hat jemand eine Idee haben, was hier vor sich geht? Ich würde wirklich schätzen jede Hilfe Sie geben können.

Ich bin mit dem Sun 1.6 Server JVM unter Windows XP 32-bit.

War es hilfreich?

Lösung

HotSpot kümmert sich nicht darum, wo der Code herkommt. Zum Beispiel wird es gerne Inline-Code durch einen virtuellen Methodenaufruf mit einer Implementierung von einem anderen Klassenlader geladen genannt.

Ich schlage vor, Sie die Vorgänge im Quellcode schreiben, die Sie für diese Benchmark auszuführen versuchen, und dann Benchmark das. Es ist in der Regel einfacher, eher ein Beispiel für generierten Code zu schreiben, als ohnehin den Generator zu schreiben.

Es gibt eine Reihe von Gründen, warum HotSpot nicht Code optimieren könnte so hart wie es könnte. Zum Beispiel werden sehr lange Methoden sind in der Regel nicht inlined werden oder Methode in sie inlined.

Andere Tipps

Ich glaube, ich verstehe, was hier los war. Mein erster Fehler Methoden wurde zu erzeugen, die zu lang waren. Nachdem ich die festen, bemerkte ich, dass, obwohl mein generierten Code noch langsamer, war es schließlich die Geschwindigkeit des interpretierten Code genähert.

Ich denke, dass die größte Speedup hier von HotSpot kommt meinen Code zu optimieren. In der interpretierten Version, gibt es sehr wenig Code zu optimieren, so HotSpot nimmt schnell darum gekümmert. In der generierten Version, gibt es eine Menge Code zu optimieren, so HotSpot länger dauert seine Magie über die gesamten Code zu arbeiten.

Wenn ich lange genug mein Benchmarks laufen, habe ich jetzt meine generierten Code Durchführung nur etwas besser als der interpretierten Code sehen.

Es gibt eine JVM-Einstellungen, die steuern, wie schnell Code sollte -XX kompiliert werden: CompileThreshold = 10000

  

Anzahl der Methodenaufrufe / Zweige vor dem Kompilieren [-client: 1500]

Ich weiß nicht, ob dies helfen wird, weil in Ihrem Beispiel die Größe scheint eine wichtige Rolle zu spielen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top