# Performanz C++ und Java



## Sonnenblume123 (24. Jun 2018)

Hallo,
die Aufgabe lautet:
Gibt es Performanzunterschiede zwischen dem []-Operator für Arrays in C++ und der get()-Methode in Java? Begründen Sie ihre Antwort in einem Satz.
Ich würde nein sagen, weil wir zwar die Speicherverwaltung in c++ haben, aber Java braucht immer die Umwege über die JVM.
Was meint ihr dazu?


----------



## httpdigest (24. Jun 2018)

Erstmal: was soll denn bitte *die* "get" Methode sein?? Es gibt keine get Methode in Java. Fakt ist: Es gibt überhaupt gar keine Methoden einfach so in Java. Es gibt Klassen. Und diese haben Methoden. Jetzt könntest du mit *der* get Methode java.util.List.get(int) meinen. Das ist aber überhaupt nicht mit irgend etwas vergleichbar, da das eine Interfacemethode ist, die in Klassen beliebig implementiert werden kann. Z. B. in Klassen wie java.util.ArrayList oder java.util.LinkedList. Wenn die Frage also ist: "Was ist der Performanceunterschied des Arrayindexierungsoperators in C/C++ und der java.util.ArrayList.get(int) Methode in Java?", dann kann man aufgrund des JIT Compilers der JVM das nicht mal eben so in einem Satz beantworten. Hier fließt immer auch der Kontext mit ein, in welchem die Arraylist verwendet wird. Escape Analysis ist zum Beispiel in der Lage, die Alloziierung der ArrayList und entsprechend des enthaltenen Arrays komplett zu entfernen. genauso ist auto-vectorization in der Lage, in einer Schleife zugegriffene, konsekutive ArrayList-Elemente per Vectorinstruktionen zu beschleunigen.
Ebenso ist Array-Bounds-Check Elimination in der Lage, die sonst zwingende Überprüfung, ob der Index in einem gültigen intervall liegt, zu entfernen, wenn bestimmte Invarianten im Code, der auf die Arraylist zugreift, eingehalten werden. Das alles spielt auch wiederum mit Escape Analysis und Inlining zusammen. Also Antwort ist: Javas Arraylist kann manchmal sogar schneller sein als C++ index operator, oder manchmal auch langsamer. Kommt drauf an.
Und nein, Java braucht nicht Umwege über die JVM. Siehe JIT compilation.


----------



## mihe7 (24. Jun 2018)

@httpdigest und das jetzt noch in einem Satz


----------



## httpdigest (24. Jun 2018)

Eine Sache habe ich noch vergessen, zu erwähnen: Falls alle diese oben genannten Performanceoptimierungen nicht greifen, und der statische Typ des zugegriffenen List-Objektes nur java.util.List ist, gibt es dann ja die Situation, dass der java.util.List.get(int) Aufruf ein Interfacemethodenaufruf ist. Das bedeutet, hier muss die JVM intern schauen, was denn der tatsächliche Typ des dahinterliegenden Objektes ist, um die implementierte/überschriebene get() Methode zu findet. Das heißt, hier gibt es single dynamic dispatch.
ABER: Die JVM ist natürlich hier auch schlau. Zwei Dinge passieren:
- Einmal: Inline Caching
- Und: Vermeidung von dynamic dispatch, wenn die einzige _gerade geladene_ Klasse, die java.util.List implementiert, die des Objektes ist, auf dem der Aufruf passiert. In diesem Fall wird der Aufruf ein direkter Methodenaufruf werden, bei dem dann auch wieder alle obig genannten Optimierungen greifen. Da vermutlich aber immer mehr als eine Klasse in der JVM geladen ist, die java.util.List implementiert (meist interne Klassen), ist das eher ein Fall, der zumindest für java.util.List nicht eintritt.
Bei Inline Caching wird die Aufrufstelle so transformiert, dass nur geprüft werden zu braucht, ob bei jedem zukünftigen Aufruf der Typ des Objektes immer noch derselbe ist, wie bei den letzten Aufrufen, und es braucht kein dynamic dispatch lookup stattfinden. Das ist sehr sehr häufig der Fall. In diesem Fall ist dann nur ein object.getClass() == oldClass Test (der sehr sehr schnell ist) nötig, und falls die Bedingung erfüllt ist, wird ein direkter (nicht-virtueller, also ohne dynamic dispatch) Aufruf auf die get() Methode gemacht.
Aber in diesen ganzen Fällen kann man schon sagen, dass rein theoretisch die get()-Methode langsamer ist, als der C/C++ Indexoperator. Aber das wird man zur Laufzeit kaum spüren. Insbesondere, wenn der Code etwa in einer Schleife ausgeführt wird, da die Speicherzugriffslatenzen zum RAM und das Füllen der CPU Caches größer sein werden als das tatsächliche Fetching, Decoding und Ausführen der Instruktionen der get() Methode.


----------

