Warum sind interface-Methoden-Aufrufe langsamer als konkrete Aufrufe?
Diese Frage kommt in den Sinn, wenn ich finden Unterschied zwischen abstrakter Klasse und Schnittstelle.
In dieser Beitrag ich kam zu wissen, dass Schnittstellen sind langsam, da Sie erforderliche zusätzliche Dereferenzierung.
Aber ich bin nicht immer welche Art der Dereferenzierung erforderlich, die durch die Schnittstelle und nicht durch die abstrakte Klasse oder konkrete Klasse.Bitte klären Sie es auf.
Vielen Dank im Voraus
- Was ist die Quelle, die dir gesagt "Schnittstellen sind langsam"?
- Schnittstellen sind nicht mehr zu Bremsen. 😉
- Die Log4J-Dokumentation besagt, "In log4j, logging-Anfragen für Instanzen von der Logger-Klasse. Logger ist eine Klasse und kein interface. Diese messbar reduziert die Kosten des Methodenaufrufs auf Kosten der Flexibilität geht." Mir, das liest sich wie, "in Zeiten, in denen extrem aggressive Optimierung ist erforderlich, - Schnittstellen kann ein Hindernis sein." Ich weiß nicht, wie genau das ist (und nie da gewesen in dieser situation, kann ich nicht bezeugen zu seiner Genauigkeit), aber es ist eine seriöse Quelle.
- Verwandte: stackoverflow.com/questions/5451775/....
- gcc.gnu.org/ml/java/1999-q4/msg00305.html
- blog.paulgu.com/2008/09/03/... auf dieser Quelle zum letzten Punkt, in dem Sie erklärte, dass die java-Schnittstellen sind langsam.
- Wäre wirklich neugierig zu sehen, der test zeigt einen messbaren Unterschied nach JIT. Log4J hat schon eine sehr sehr lange Zeit, kann glauben, dass das wahr war vor 12 Jahren, bevor es war sogar 1.4.2 hotspot. Schwer zu glauben, dass es zu messbaren Unterschied würde es nach JIT-auf eine moderne JVM.
- Gut, mein Gedanke ist, "Macht es wirklich so viel Unterschied auf moderne Architektur? Wir sind in einer Welt, wo solche Optimierungen sind für Menschen, die 'nicht leisten können RAM'"
- dein Erster post ist über gcj, die eine schreckliche Java-implementation (Sie hat einen notwendigen job, aber in reiner Qualität in der Produktion, es war nie wirklich gut). Ihre zweite link besagt lediglich, als wäre es eine Tatsache und gibt keine Hinweis darauf, wie er zu diesem Schluss gekommen. Die Chancen sind, er Las es in einem 10 Jahre alten Artikel selbst.
- es;s nicht nur über RAM oder Optimierung, sondern um zu lernen, grundlegende Konzepte.nun wird ein Tag jeder kann die kaufen, sehr konfigurierten system, aber kein können, sondern Konzepte der Programmierung,
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gibt es viele performance-Mythen, und einige waren wahrscheinlich wahr vor einigen Jahren, und einige würden immer noch wahr sein, bei VMs, die keine JIT.
Die Android-Dokumentation (denken Sie daran, dass Android nicht über eine JVM, Sie haben Dalvik VM) verwendet, um zu sagen, dass das aufrufen einer Methode eines interfaces war langsamer als die Berufung auf Sie für eine Klasse, so waren Sie es, einen Beitrag zur Verbreitung des Mythos (es ist auch möglich, dass es langsamer war auf der Dalvik VM, bevor Sie drehte sich auf die JIT). Die Dokumentation wird jetzt sagen:
Quelle: Designing for performance auf Android
Das gleiche gilt wohl auch für die JIT der JVM, es wäre sehr seltsam, sonst.
Wenn Sie Zweifel haben, Messen Sie es. Meine Ergebnisse zeigten keinen signifikanten Unterschied. Wenn ausführen, wird das folgende Programm erzeugt:
Aber wenn ich wechselte die Orte, an die zwei Schleifen:
Scheint es, dass abstrakte Klassen sind etwas (~6%) schneller, aber das sollte nicht bemerkbar sein; Diese sind Nanosekunden. 7887080 Nanosekunden sind ~7 Millisekunden. Macht es einen Unterschied von 0,1 millis pro 40k Aufrufe (Java-version: 1.6.20)
Hier der code:
Dies ist variation auf Bozho Beispiel. Es läuft mehr und re-verwendet die gleichen Objekte, so dass die cache-Größe spielt keine Rolle, so viel. Ich benutze auch ein array, so gibt es keinen overhead aus dem iterator.
Drucke
wenn Sie die Reihenfolge tauschen Sie die tests ausführen, erhalten Sie
Da ist mehr Unterschied, wie Sie den test ausführen, als welche Sie wählen.
Bekam ich das gleiche Ergebnis mit Java 6 update 26 und OpenJDK 7.
BTW: Wenn Sie das hinzufügen einer Schleife, die nur dann aufrufen, das gleiche Objekt jedes mal, erhalten Sie
4.2
und4.1
ist nicht2
...Ein Objekt hat eine "vtable-Zeiger" von einer Art, die Punkte zu einem "vtable" (Methode Zeiger-Tabelle) für die Klasse ("vtable" ist wohl die falsche Terminologie, aber das ist nicht wichtig). Die vtable Zeiger auf alle Implementierungen von Methoden; jede Methode hat ein index entspricht einem Tabelleneintrag. So, zum Aufruf einer Methode der Klasse, die Sie gerade schauen Sie oben die entsprechende Methode (über den index) in der vtable. Wenn eine Klasse erweitert eine andere, es hat nur eine längere vtable mit mehr Einträge; Aufruf einer Methode aus der Basisklasse verwendet immer noch die gleiche Prozedur: das heißt, Sie sehen die Methode durch den index.
Jedoch, in den Aufruf einer Methode aus einer Schnittstelle, die über eine interface-Referenz, muss es einen alternativen Mechanismus zu finden, der die Implementierung der Methode Zeiger. Denn eine Klasse kann mehrere interfaces implementieren, es ist nicht möglich, für die Methode immer den gleichen index in der vtable (zum Beispiel). Es gibt verschiedene Möglichkeiten, diese zu lösen, aber no way, die ist nicht ganz so effizient wie einfach vtable-Versand.
Jedoch, wie bereits erwähnt in den Kommentaren, es wahrscheinlich nicht viel Unterschied mit einem modernen Java-VM-Implementierung.
Habe ich versucht, einen test schreiben, würde Quantifizierung der verschiedenen Möglichkeiten, die Methoden, die möglicherweise aufgerufen werden. Meine Ergebnisse zeigen, dass es ist nicht, ob es eine Methode ist eine Schnittstelle, die Methode oder nicht, was zählt, sondern eher der Typ der Referenz, über die Sie aufgerufen wird. Aufruf einer interface-Methode durch eine class-Referenz ist viel schneller (relativ zur Anzahl der Anrufe) als Aufruf der gleichen Methode, die auf der gleichen Klasse über eine Referenz zur Benutzeroberfläche Referenz.
Die Ergebnisse für 1.000.000 Aufrufe sind...
interface-Methode über die interface-Referenz: (nanos, millis) 5172161.0, 5.0
interface-Methode über abstrakte Referenz: (nanos, millis) 1893732.0, 1.8
interface-Methode über toplevel abgeleitet, Referenz: (nanos, millis) 1841659.0, 1.8
Konkrete Methode über konkrete Klasse Referenz: (nanos, millis) 1822885.0, 1.8
Beachten Sie, dass die ersten zwei Zeilen sind die Ergebnisse fordert, um genau die gleiche Methode, aber mit anderen Referenzen.
Und hier ist der code...
Diese wurde mit dem Oracle JDK 1.6_24. Hoffe, dies hilft, diese Frage stellen zu Bett...
Grüße,
Rodney Barbati
Schnittstellen sind langsamer als abstrakte Klasse, die als Laufzeit-Entscheidung des Methodenaufrufs möchte hinzufügen wenig Strafe Zeit,
Jedoch als JIT-kommt-im-Bild, die kümmern sich um wiederholte Aufrufe der gleichen Methode, also können Sie sehen, die Leistung lag nur in der ersten rufen, die ist auch sehr minimal,
Nun für Java 8, dass Sie fast abstrakten Klasse sinnlos durch hinzufügen von Standard & statische Funktion,