2017-09-10 2 views
0

Immer wenn ich Async-Code in Java schreibe, muss ich eine Runnable (Function, Callable, ...) oder eine neue Lambda-Syntax verwenden. Es gibt keine Garantie, dass es vom Compiler eingebunden wird, anders als beispielsweise C++ - Vorlagen.Die Kosten von Runnable in HotSpot

In welchen Fällen kann es vom Compiler optimiert werden, was bedeutet etwas effizienter als die Instanziierung eines Runnable Objekts? Was ist mit JIT? Zum Beispiel, Stream-Operationen, Lazy Init, Callbacks?

Wenn es nicht optimiert ist, kann HotSpot Millionen von Runnable Instanzen verwalten, ohne dass ein erheblicher Overhead für GC entsteht? Im Allgemeinen, sollte ich jemals von einer umfangreichen Verwendung der Lambdas und Rückrufe in einer Anwendung betroffen sein?

+2

Es ist viel wahrscheinlicher, dass andere Leistungsprobleme auftreten. Sie sollten sich also nicht zu sehr darum kümmern. – Kayaman

+0

Wie soll der asynchrone Code inline sein? Wenn es inline wird, wäre es nicht asynchron. Das gilt natürlich auch für C++. Der Executor muss etwas mit einer Identität erhalten, um zu wissen, was ausgeführt werden soll, und das ist normalerweise ein Speicherort in C++. Daher ist das Reservieren von Speicher für die Darstellung des asynchronen Jobs unvermeidlich. Die einzige Ausnahme wäre das wiederholte Ausführen der gleichen invarianten Operation, und in diesem Fall würden Java- Lambda-Ausdrücke oder Methodenreferenzen auch für das gleiche Objekt ausgewertet werden. – Holger

Antwort

1

Zunächst müssen Sie verstehen, was der Javac Compiler macht und was die JVM über den JIT Compiler macht.

Runnable ist eine Schnittstelle, so dass Sie entweder eine Klasse erstellen können, die diese Schnittstelle implementiert, und dann eine Instanz an den Thread-Konstruktor übergeben, oder Sie können eine anonyme innere Klasse (AIC) verwenden. In diesem Fall generiert der Compiler javac eine synthetische Klasse für Sie, die Runnable implementiert und eine Instanz für Sie erstellt.

C++ verwendet die statische AOT-Kompilierung und, wie Sie sagen, können Inline-Vorlagen. Die JVM verwendet eine adaptive jit-in-time (JIT) -Kompilierung. Wenn eine Klassendatei geladen wird, werden die Bytecodes interpretiert, bis die JVM feststellt, dass es Hotspots im Code gibt, und sie zu nativen Anweisungen kompiliert, die zwischengespeichert werden können. Wie aggressiv die verwendeten Optimierungen sind, hängt vom verwendeten JIT ab. Der OpenJDK hat zwei JITs, C1 und C2 (manchmal auch als Client und Server bezeichnet). C1 kompiliert Code schneller, optimiert aber weniger. C2 dauert länger zum kompilieren, optimiert aber mehr. Die run() Methode Ihrer Runnable wird inline, wenn der Compiler entscheidet, dass das die beste Optimierung ist (was bedeutet, dass es am wahrscheinlichsten ist, wenn es stark verwendet wird). Wir bei Azul (ich arbeite für sie) haben kürzlich eine neue JVM JIT namens Falcon basierend auf LLVM veröffentlicht, die noch weiter optimiert.

Lambdas sind ein bisschen anders. Jeder Lambda-Ausdruck kann in einen äquivalenten AIC konvertiert werden und für die frühe Implementierung in JDK 8 wurden sie so implementiert, als syntaktischer Zucker zu einem AIC. Um die Leistung zu optimieren, generiert javac jetzt Code, der stattdessen den invokedynamic Bytecode verwendet. Dadurch wird die Implementierung eines Lambda in der JVM vermieden, anstatt es in der Klassendatei hart zu codieren. Die JVM kann eine AIC verwenden, sie kann eine statische Methode oder eine andere Implementierungsmethode verwenden. Als kleiner Punkt ist die Verwendung einer Methodenreferenz und nicht eines expliziten Lambda für die Leistung sehr geringfügig besser.

Für den GC-Aspekt Ihrer Frage hängt es vom Profil Ihres Codes ab. Wenn Sie Millionen von Runnable Objekte verwenden, wäre ich mehr besorgt über die Auswirkungen der Thread Objekte. Wenn Sie diese nicht bündeln, ist der GC-Aufwand beim Erstellen und Sammeln von Millionen von Threads weitaus größer als der der Runnable Objekte. Solange die Runnable Objekte im Eden-Raum gesammelt werden können, ist der Overhead effektiv Null.