Ich möchte ein neues Array von Objekten erstellen, die zwei kleinere Arrays zusammensetzen.
Sie können nicht null sein, aber die Größe kann 0 sein.
Ich kann nicht zwischen diesen beiden Möglichkeiten wählen: Sind sie gleichwertig oder ist eine effizienter (zum Beispiel system.arraycopy () kopiert ganze Blöcke)?
MyObject[] things = new MyObject[publicThings.length+privateThings.length];
System.arraycopy(publicThings, 0, things, 0, publicThings.length);
System.arraycopy(privateThings, 0, things, publicThings.length, privateThings.length);
oder
MyObject[] things = new MyObject[publicThings.length+privateThings.length];
for (int i = 0; i < things.length; i++) {
if (i<publicThings.length){
things[i] = publicThings[i]
} else {
things[i] = privateThings[i-publicThings.length]
}
}
Ist der einzige Unterschied das Aussehen des Codes?
EDIT: Danke für die verknüpfte Frage, aber sie scheinen eine ungelöste Diskussion zu haben:
Ist es wirklich schneller, wenn it is not for native types
: Byte [], Objekt [], Zeichen []? in allen anderen Fällen wird eine Typprüfung durchgeführt, was mein Fall wäre und daher gleichwertig wäre ... nein?
Bei einer anderen verknüpften Frage heißt es, dass the size matters a lot
bei einer Größe von> 24 system.arraycopy () für weniger als 10 das Handbuch für die Schleife besser ist ...
Jetzt bin ich wirklich verwirrt.
arraycopy()
ist ein nativer Anruf, der mit Sicherheit schneller ist.Antworten:
Ich weiß, dass JUnit-Tests nicht wirklich die besten für das Benchmarking sind, aber
testHardCopyBytes dauerte 0,157 Sekunden
und
testArrayCopyBytes 0,086 Sekunden.
Ich denke, es hängt von der virtuellen Maschine ab, aber es sieht so aus, als würde sie Speicherblöcke kopieren, anstatt einzelne Array-Elemente zu kopieren. Dies würde die Leistung absolut steigern.
EDIT:
Es sieht so aus, als ob die Leistung von System.arraycopy allgegenwärtig ist. Wenn Strings anstelle von Bytes verwendet werden und Arrays klein sind (Größe 10), erhalte ich folgende Ergebnisse:
So sieht es aus, wenn Arrays die Größe 0x1000000 haben. Es sieht so aus, als ob System.arraycopy mit größeren Arrays definitiv gewinnt.
Wie eigenartig!
Vielen Dank, Daren, dass Sie darauf hingewiesen haben, dass Referenzen anders kopiert werden. Das machte das Problem viel interessanter!
quelle
Arrays.copyOf(T[], int)
ist leichter zu lesen. InternSystem.arraycopy()
wird ein nativer Anruf verwendet.Schneller geht es nicht!
quelle
copyOf
kann nicht immer ersetzenarraycopy
, ist aber für diesen Anwendungsfall geeignet.Dies hängt von der virtuellen Maschine ab, aber System.arraycopy sollte Ihnen die bestmögliche Leistung bieten.
Ich habe 2 Jahre als Java-Entwickler für eingebettete Systeme gearbeitet (wo Leistung eine große Priorität hat) und überall dort, wo System.arraycopy verwendet werden konnte, habe ich es meistens in vorhandenem Code verwendet / gesehen. Es wird immer Schleifen vorgezogen, wenn die Leistung ein Problem darstellt. Wenn die Leistung kein großes Problem darstellt, würde ich mich jedoch für die Schleife entscheiden. Viel einfacher zu lesen.
quelle
Arrays.copy
existiert nicht,Arrays.copyOf
ist eine Bibliotheksfunktion.Anstatt mich auf Spekulationen und möglicherweise veraltete Informationen zu verlassen, habe ich einige Benchmarks verwendet Bremssattel. In der Tat kommt Caliper mit einigen Beispielen, einschließlich eines
CopyArrayBenchmark
, das genau diese Frage misst! Alles was Sie tun müssen, ist zu rennenMeine Ergebnisse basieren auf der 64-Bit-Server-VM Java HotSpot (TM) von Oracle, 1.8.0_31-b13, die Mitte 2010 auf einem MacBook Pro (macOS 10.11.6 mit Intel Arrandale i7, 8 GiB RAM) ausgeführt wird. Ich glaube nicht, dass es nützlich ist, die rohen Timing-Daten zu veröffentlichen. Vielmehr werde ich die Schlussfolgerungen mit den unterstützenden Visualisierungen zusammenfassen.
Zusammenfassend:
for
Schleife zum Kopieren jedes Elements in ein neu instanziiertes Array ist niemals vorteilhaft, sei es für kurze oder lange Arrays.Arrays.copyOf(array, array.length)
undarray.clone()
sind beide konstant schnell. Diese beiden Techniken sind in der Leistung nahezu identisch. Welches Sie wählen, ist Geschmackssache.System.arraycopy(src, 0, dest, 0, src.length)
ist fast so schnell wie und , aber nicht ganz konsequent. (Siehe den Fall für 50000 s.) Aus diesem Grund und aufgrund der Ausführlichkeit des Aufrufs würde ich empfehlen, wenn Sie eine genaue Kontrolle darüber benötigen, welche Elemente wohin kopiert werden.Arrays.copyOf(array, array.length)
array.clone()
int
System.arraycopy()
Hier sind die Zeitdiagramme:
quelle
Das Ausführen nativer Methoden wie hat
Arrays.copyOf(T[], int)
zwar einen gewissen Overhead, bedeutet jedoch nicht, dass es nicht schnell ist, da Sie es mit JNI ausführen.Am einfachsten ist es, einen Benchmark zu schreiben und zu testen.
Sie können überprüfen, ob dies
Arrays.copyOf(T[], int)
schneller als Ihre normalefor
Schleife ist.Der Benchmark-Code von hier : -
System.arraycopy()
verwendet JNI (Java Native Interface) zum Kopieren eines Arrays (oder von Teilen davon), so dass es unglaublich schnell ist, wie Sie hier bestätigen könnenquelle
System.arraycopy
benutzt es nicht.System.arraycopy
verwendet kein JNI, das nur zum Aufrufen von Bibliotheken von Drittanbietern dient. Stattdessen handelt es sich um einen nativen Aufruf. Dies bedeutet, dass in der VM eine native Implementierung vorhanden ist.Es ist nicht möglich, dass dies
Arrays.copyOf
schneller ist alsSystem.arraycopy
da dies die Implementierung voncopyOf
:quelle
System.arraycopy()
ist ein nativer Aufruf, der Kopiervorgänge direkt im Speicher ausführt. Eine einzelne Speicherkopie wäre immer schneller als Ihre for-Schleifequelle