Ich war überrascht, in der Java-Quelle zu sehen, dass System.arraycopy eine native Methode ist.
Der Grund ist natürlich, dass es schneller ist. Aber welche nativen Tricks kann der Code anwenden, um ihn schneller zu machen?
Warum nicht einfach das ursprüngliche Array durchlaufen und jeden Zeiger auf das neue Array kopieren - das ist doch nicht so langsam und umständlich?
arraycopy
mitmemcpy
/ implementiert werdenmemmove
. Andere erfordern eine Laufzeit-Typprüfung für jedes kopierte Element.Object[]
mitString
Objekten besetzten Objekt nach aString[]
. Siehe letzten Absatz von java.sun.com/javase/6/docs/api/java/lang/…Es kann nicht in Java geschrieben werden. Native Code kann den Unterschied zwischen Arrays von Object und Arrays von Primitiven ignorieren oder beseitigen. Java kann das nicht, zumindest nicht effizient.
Und es kann
memcpy()
aufgrund der Semantik, die überlappende Arrays erfordern, nicht mit einem einzigen geschrieben werden .quelle
memmove
dann. Obwohl ich nicht denke, dass es im Kontext dieser Frage einen großen Unterschied macht.Dies hängt natürlich von der Implementierung ab.
HotSpot behandelt es als "intrinsisch" und fügt Code an der Anrufstelle ein. Das ist Maschinencode, kein langsamer alter C-Code. Dies bedeutet auch, dass die Probleme mit der Signatur der Methode weitgehend verschwinden.
Eine einfache Kopierschleife ist so einfach, dass offensichtliche Optimierungen darauf angewendet werden können. Zum Beispiel das Abrollen der Schleife. Was genau passiert, hängt wiederum von der Implementierung ab.
quelle
In meinen eigenen Tests ist System.arraycopy () zum Kopieren von Arrays mit mehreren Dimensionen 10 bis 20 Mal schneller als das Verschachteln von Schleifen:
Dies druckt:
quelle
System.arraycopy
führt eine flache Kopie durch (nur die Verweise auf die innerenfloat[]
s werden kopiert), während Ihre verschachteltenfor
Schleifen eine tiefe Kopie (float
vonfloat
) ausführen . Eine Änderung anfooCpy[i][j]
wird in derfoo
Verwendung berücksichtigtSystem.arraycopy
, verwendet jedoch nicht die verschachteltenfor
Schleifen.Es gibt einige Gründe:
Es ist unwahrscheinlich, dass die JIT so effizienten Low-Level-Code generiert wie ein manuell geschriebener C-Code. Die Verwendung von Low Level C kann viele Optimierungen ermöglichen, die für einen generischen JIT-Compiler nahezu unmöglich sind.
Unter diesem Link finden Sie einige Tricks und Geschwindigkeitsvergleiche von handgeschriebenen C-Implementierungen (memcpy, aber das Prinzip ist dasselbe): Aktivieren Sie dieses Kontrollkästchen Optimieren von Memcpy verbessert die Geschwindigkeit
Die C-Version ist weitgehend unabhängig von Typ und Größe der Array-Mitglieder. In Java ist dies nicht möglich, da es keine Möglichkeit gibt, den Array-Inhalt als unformatierten Speicherblock (z. B. Zeiger) abzurufen.
quelle