2011-01-07 4 views
4

Ich habe eine Methode, die viel Zeit braucht, um das erste Mal auszuführen. Aber nach mehreren Aufrufen dauert es etwa 30 mal weniger Zeit. Um meine Anwendung schneller auf Benutzerinteraktionen reagieren zu lassen, "warm-up" ich diese Methode (5 Mal) mit einigen Beispieldaten bei der Initialisierung der Anwendung. Dies erhöht jedoch die Startzeit der App.
Ich lese, dass JVMs meinen Java-Code optimieren und kompilieren können, um Dinge schneller zu machen. Ich wollte wissen - vielleicht gibt es eine Möglichkeit, JVM explizit zu sagen, dass ich diese Methode beim Start der Anwendung kompiliert werden soll?Gibt es eine Möglichkeit, JVM mitzuteilen, meinen Code vor der Verarbeitung zu optimieren?

+1

Sind Sie wirklich sicher, dass es besser ausführt, nachdem wegen der JVM Optimierungen mehrmals genau aufgerufen werden. Abhängig davon, was Ihre Methode tut, könnte es auch etwas anderes sein - zum Beispiel Disketten- oder Datenbank-Caching ... –

+0

@Rogach: Können Sie Ihre Methode nicht zuerst optimieren? Was für Sachen macht es? – Gugussee

+0

Was genau macht diese Methode? – Cratylus

Antwort

6

Die JVM optimiert JiT (Just in Time) zur Laufzeit. Dies bedeutet, dass Sie analysieren können, wie Ihr Code ausgeführt wird, und Optimierungen vornehmen, um die Laufzeitleistung zu erhöhen. Dies geschieht bei Laufzeit. Wenn Sie feststellen, dass die Methode nach einigen Ausführungen schneller wird, liegt das wahrscheinlich an den JiT-Optimierungen (es sei denn, Ihre Analyse ist fehlerhaft und die Methode wird z. B. schneller, weil die Daten einfacher werden). Wenn die Analyse korrekt ist, kann das Kompilieren zu nativ möglicherweise Sie verletzen, da Sie keine Laufzeitoptimierungen mehr erhalten.

Können wir die Methode sehen? Sie können es vielleicht schneller machen, ohne sich darum kümmern zu müssen, wie die JVM funktioniert. Sie sollten genau isolieren, wo die teuersten Operationen sind. Sie sollten außerdem überprüfen, dass dies kein Garbage Collection-Problem ist. vielleicht ist die Methode in Ordnung, aber es gibt einen GC, der die Zeit auffrisst, und wenn es fertig ist, läuft die Methode mit akzeptablen Geschwindigkeiten.

+0

in Bezug auf den zweiten Absatz, gibt es ein gutes Werkzeug, um die Ausführung eines Java-Programms zu profilieren? Etwas wie Shark zum Beispiel (afaik, Shark! Funktioniert nur für Macintosh, und für "C-like" code) – posdef

+0

@posdef, ich habe SO nach 'best free java profiler' gesucht und http://stackoverflow.com/questions bekommen/163722/which-java-profiler-is-besser-jprofiler-or-yourkit – hvgotcodes

3

die JIT-Optimierungen funktionieren so gut, gerade weil sie zu optimieren, was Ihr Code tatsächlich tut, und was es nicht konnte in verschiedenen Fällen tun.

Es ist sogar möglich, dass der JITted-Code in verschiedenen Läufen aufgrund unterschiedlicher Eingabedaten unterschiedlich ist. Oder es könnte sogar mehr als einmal neu optimiert werden, wenn sich die Umstände ändern.

Mit anderen Worten: Ohne echte Daten wird die JVM keinen guten Job machen, um den Code zu optimieren. (Dh es kann nur tun, ‚statische‘ Optimierungen)

Aber am Ende, wenn Sie so hohe Verbesserung bekommen (30x ist eine Menge!), Ist es sehr wahrscheinlich, dass es entweder

  • nicht die Code aber etwas anderes (wie Datei- oder Datenbankcaches)
  • sehr nicht optimaler Code auf Quellniveau. (Wie einige schwere Berechnungen, die von engen Schleifen gehen könnte)

EDIT:

Nachdem in Ihrem Code suchen, in einer großen Schleife auf Literas.prepareLiteras(), sind Sie ständig path.contains(p) mit verschiedenen Punkten fordern aber der gleiche Weg. SimplePath.contains() erstellt bei jedem Aufruf eine Begrenzungsform, sodass Sie immer wieder dieselbe Form erstellen. Das ist ein Paradebeispiel für etwas, das aus der inneren Schleife herausgezogen werden sollte.

Ich glaube nicht, dass das JIT diese ganze Methode weg optimieren kann, aber in einigen extremen Fällen könnte es die getShape() in etwas Spezialisiertes für einen einzelnen Pfad konvertieren und für den nächsten Pfad erneut kompilieren. Nicht eine gute Verwendung von JVM Smart, nicht wahr?

2

Wenn Sie die Sun JVM verwenden, gibt es unterschiedliche Schwellenwerte für die JIT-Kompilierung, je nachdem, ob Sie die Client- oder die Server-JVM verwenden. Für den Client sind das 1500 Aufrufe einer Methode, für den Server 10000. Sie können dies mit dem JVM-Parameter -XX:CompileThreshold=100 auf einen sehr niedrigen Wert ändern.

Eine so niedrige Schwelle wird Ihrer globalen Leistung jedoch nicht zugute kommen. Ich empfehle nur, es zu verwenden, um zu testen, ob die Leistungsverbesserung durch Aufwärmen von JIT beeinflusst wird.

Ich habe noch nie eine Verbesserung mit dem Faktor 30 durch Warm-up gesehen, die auf JIT-Optimierungen zurückzuführen war. Noch. Es war immer wegen einiger Caches.

+0

Wow. Es tötet fast die App. Ja, es scheint, dass Verbesserungen nicht das Ergebnis von JIT sind. Dieser Parameter macht die Dinge tatsächlich viel langsamer. – Rogach

+2

Nun, dann versuchen Sie einen Profiler. Aktuelle JDKs enthalten JVisualVM, das mit einem grundlegenden Profiler geliefert wird. –

2

Sie können versuchen, dies auf einer 64-Bit-JVM auszuführen, wenn Sie ein 64-Bit-Betriebssystem haben.

Es gibt zwei Versionen der JVM in der Implementierung von Oracle: die Client-VM und die Server-VM. Bei 32-Bit-Windows ist die Client-VM die Standardeinstellung. Auf 64-Bit-Windows ist die Server-VM die Standardeinstellung.

Der Unterschied zwischen der Client- und der Server-VM besteht darin, wie sie abgestimmt sind: Die Server-VM führt aggressivere Optimierungen durch (und macht sie früher) als die Client-VM. Die Server-VM hat Einstellungen für lange laufende Prozesse optimiert. Die Client-VM verfügt über Standardeinstellungen, die für die Verwendung auf dem Desktop optimiert sind: Sie führt weniger Optimierungen durch, startet jedoch schneller.

Ich habe große Geschwindigkeitsunterschiede in rechenintensiven Programmen erlebt; Diese laufen bei einer 64-Bit-JVM manchmal doppelt so schnell wie bei einer 32-Bit-JVM.

1

Meistens würde ich hvgotcodes dito, aber es ist auch möglich, dass das Problem nicht JVM-Optimierung ist, aber dass nach den ersten paar Durchläufe von Daten von einem Datenträger jetzt im Cache ist, oder dass die ersten Male es immer noch ist Klassen laden und initialisieren, aber danach sind sie alle im Speicher.

Verwandte Themen