Liste RandNums mit 10 Millionen Elementen benötigt ca. 700 MB Speicherplatz. Um die Auswirkungen von GC zu vermeiden (Sicher, es viel in diesem Test bedeutet), stelle ich die Hotspot VM Argumente wie folgt aus:
-XX:+PrintGC
-XX:+PrintGCTimeStamps
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-Xmx1000m
-Xms1000m
-Xmn999m
-XX:SurvivorRatio=65535
Junge Generation groß genug, um alle Elemente zu speichern und keine GC machen während der Elementzuordnung. Ich mache Eden Region of Young Generation größer, um zu vermeiden, dass Elemente in Young Generation kopiert werden.
Das Ergebnis ist überraschend!. Die gesamte Ausführungszeit verringert sich von 8s auf 0,6s!
Hier habe ich etwas mehr Arbeit für den Fragesteller getan, das testet, ob die Vor-Zuweisung von ArrayList Zeit spart und wie viel es hilft.
Hier ist mein Code:
long startTime;
List<String> randNums;
Random r = new Random(1);
System.out.println("-----------------------------ArrayList With Enough Capacity Allocated:----------");
for(int loop=0;loop<5;loop++) {
startTime = System.currentTimeMillis();
randNums = new ArrayList<String>(SIZE);
for (int i = 0; i <SIZE ; i++) {
int randomNum = r.nextInt();
randNums.add(Integer.toString(randomNum));
}
System.out.println(System.currentTimeMillis() - startTime); //print time of this loop
randNums.clear();
System.gc();
}
System.out.println("\n-----------------------------ArrayList Auto-Capacity:----------");
for(int loop=0;loop<5;loop++) {
startTime = System.currentTimeMillis();
randNums = new ArrayList<String>();
for (int i = 0; i <SIZE ; i++) {
int randomNum = r.nextInt();
randNums.add(Integer.toString(randomNum));
}
System.out.println(System.currentTimeMillis() - startTime); //print time of this loop
randNums.clear();
System.gc();
}
Die Ausgabe lautet:
-----------------------------ArrayList With Enough Capacity Allocated:----------
625
0.712: [Full GC (System.gc()) 714143K->39628K(1023936K), 0.1450449 secs]
0.863: [GC (CMS Initial Mark) 98268K(1023936K), 0.0549729 secs]
545
1.413: [Full GC (System.gc()) 705185K->564K(1023936K), 0.1239084 secs]
483
2.031: [Full GC (System.gc()) 679570K->564K(1023936K), 0.1256323 secs]
2.160: [GC (CMS Initial Mark) 59357K(1023936K), 0.0274108 secs]
523
2.688: [Full GC (System.gc()) 670987K->564K(1023936K), 0.1222910 secs]
482
3.302: [Full GC (System.gc()) 673223K->564K(1023936K), 0.1299938 secs]
-----------------------------ArrayList Auto-Capacity:----------
3.432: [GC (CMS Initial Mark) 40961K(1023936K), 0.0003740 secs]
3.907: [GC (CMS Final Remark) 698381K(1023936K), 0.1091347 secs]
796
4.240: [Full GC (System.gc()) 911984K->56183K(1023936K), 0.1719540 secs]
4.412: [GC (CMS Initial Mark) 56183K(1023936K), 0.0394210 secs]
4.770: [GC (CMS Final Remark) 528894K(1023936K), 0.0726012 secs]
690
5.111: [Full GC (System.gc()) 893818K->2060K(1023936K), 0.1364215 secs]
5.248: [GC (CMS Initial Mark) 20769K(1023936K), 0.0008902 secs]
5.750: [GC (CMS Final Remark) 694113K(1023936K), 0.1124856 secs]
704
5.962: [Full GC (System.gc()) 808646K->2081K(1023936K), 0.1338328 secs]
6.096: [GC (CMS Initial Mark) 21137K(1023936K), 0.0010118 secs]
6.599: [GC (CMS Final Remark) 688155K(1023936K), 0.0899929 secs]
661
6.767: [Full GC (System.gc()) 810872K->2081K(1023936K), 0.1287272 secs]
6.896: [GC (CMS Initial Mark) 21512K(1023936K), 0.0010619 secs]
7.398: [GC (CMS Final Remark) 691216K(1023936K), 0.1083076 secs]
681
7.586: [Full GC (System.gc()) 803590K->2081K(1023936K), 0.1269813 secs]
7.714: [GC (CMS Initial Mark) 2081K(1023936K), 0.0008965 secs]
Striping GC Info, es ist:
-----------------------------ArrayList With Enough Capacity Allocated:----------
615
540
480
511
480
-----------------------------ArrayList Auto-Capacity:----------
680
708
640
644
663
Wir verwendet letzten drei Daten jeder Gruppe die Optimierung berechnen (um JIT- und VM-Optimierung zu vermeiden). Die Antwort kommt so:
Ich sehe dieses Verhalten nicht, wenn ich es auf meinem Laptop versuche, aber das ist wahrscheinlich plattformabhängig. Das einzige, was ich mir vorstellen kann, ist, dass wenn Sie Platz für das gesamte Array auf einmal reservieren, es am Ende den Speicher auslagern könnte, was die Dinge verlangsamen könnte. – ajb
welche JVM? 64bit java verwendet standardmäßig den 'server' vm, der JIT-kompiliert aggressiver als der Standard-vm für 32bit Java. So sehen Sie manchmal seltsame Perf Unterschiede mit 32bit Java für Dinge, die ein anständiger JIT-Compiler weg optimieren würde. –
Was Sie sehen, ist wahrscheinlich Lärm. Versuchen Sie, jedes Mal "1" hinzuzufügen, anstatt die Zufallsgenerierung durchzuführen. –