Some regression when using initial capacity for ArrayList at first iterations

I am a bit confused. In the first iterations of fill cycles, I see some regression during fill when using initial capacity for ArrayList vs without using initial capacity.

According to common sense and this question: Why start an ArrayList with initial throughput?

it should be absolutely back.

This is not a well-written test test , and I am wondering: why does it always consume much more time and processor during the first iteration when using the initial capacity for ArrayList ?

This is a test:

 public class TestListGen { public static final int TEST = 100_000_000; public static void main(String[] args) { test(false); } private static void test(boolean withInitCapacity) { System.out.println("Init with capacity? " + withInitCapacity); for (int i = 0; i < 5; i++) av += fillAndTest(TEST, withInitCapacity ? new ArrayList<Integer>(TEST) : new ArrayList<Integer>()); System.out.println("Average: " + (av / 5)); } private static long fillAndTest(int capacity, List<Integer> list) { long time1 = System.nanoTime(); for (int i = 0; i < capacity; i++) list.add(i); long delta = System.nanoTime() - time1; System.out.println(delta); return delta; } } 

Conclusion: 1)

 Init with capacity? false 17571882469 12179868327 18460127904 5894883202 13223941250 Average: 13466140630 

2)

 Init with capacity? true 37271627087 16341545990 19973801769 4888093008 2442179779 Average: 16183449526 

I tested it: JDK 1.7.0.40 , JDK 1.8.0.31

+6
source share
1 answer

This is an artifact of the Java heap placement that causes the expected results. Adjust the initial distribution of the heap and you will see more consistent results, removing the time for heap allocation from the mix. In addition, you must be sure that the process on which the benchmark is running is not replaced. On my system, I received an OOM error when TEST = 100_000_000 and I had to reduce it to 10_000_000 for my tests. In addition, I ran both test(false) and test(true) one after the other. Note how allocating a heap at startup and adding explicit gc to the results below make individual times more consistent. Adding a back warm-up would also be important in order to make the test more consistent, but I did not worry about it.

Original test

 Init with capacity? false 1714537208 1259523722 1215986030 1098740959 1029914697 Average: 1263740523 Init with capacity? true 343100302 612709138 355210333 603609642 348401796 Average: 452606242 

Test with -Xms500m -Xmx500m

 Init with capacity? false 682827716 738137558 576581143 662777089 555706338 Average: 643205968 Init with capacity? true 368245589 312674836 297705054 392935762 307209139 Average: 335754076 

Test from -Xms500m -Xmx500m + System.gc() to fillAndTest()

 Init with capacity? false 502767979 435508363 420956590 487184801 416041923 Average: 452491931 Init with capacity? true 300744404 298446734 299080656 300084036 298473576 Average: 299365881 
+2
source

Source: https://habr.com/ru/post/984236/


All Articles