Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在第一次迭代中使用ArrayList的初始容量时的一些回归_Java_Performance_Arraylist - Fatal编程技术网

Java 在第一次迭代中使用ArrayList的初始容量时的一些回归

Java 在第一次迭代中使用ArrayList的初始容量时的一些回归,java,performance,arraylist,Java,Performance,Arraylist,我有点困惑。在填充循环的第一次迭代中,我看到在使用initial capacityforArrayListvs而不使用initial capacity时,填充时间出现了一些回归 根据常识和这个问题: 它必须是绝对相反的 它的基准测试编写得不好,我想知道:为什么在第一次迭代中使用ArrayList的初始容量时总是要消耗更多的时间和CPU 这就是测试: public class TestListGen { public static final int TEST = 100_000_000;

我有点困惑。在填充循环的第一次迭代中,我看到在使用
initial capacity
for
ArrayList
vs而不使用initial capacity时,填充时间出现了一些回归

根据常识和这个问题:

它必须是绝对相反的

它的基准测试编写得不好,我想知道:为什么在第一次迭代中使用
ArrayList的初始容量时总是要消耗更多的时间和CPU

这就是测试:

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;
    }
}
(二)


我已经对它进行了测试:
jdk1.7.0.40
jdk1.8.0.31

这是一个Java堆分配工件,导致了您意想不到的结果。调整初始堆分配,通过从混合中删除堆分配时间,您将看到更一致的结果。此外,您需要确保运行基准的进程没有被交换。在我的系统上,当
TEST=100_000_000
时,我得到了一个OOM错误,我必须将其减少到
10_000_000
。我还一个接一个地运行了
test(false)
test(true)
。请注意,在启动时分配堆和在下面的结果中添加显式gc如何使各个时间更加一致。再加上一次热身对于使测试更加一致也很重要,但我并不为此烦恼

原始测试

Init with capacity? false
1714537208
1259523722
1215986030
1098740959
1029914697
Average: 1263740523
Init with capacity? true
343100302
612709138
355210333
603609642
348401796
Average: 452606242
使用
-Xms500m-Xmx500m测试

Init with capacity? false
682827716
738137558
576581143
662777089
555706338
Average: 643205968
Init with capacity? true
368245589
312674836
297705054
392935762
307209139
Average: 335754076
Init with capacity? false
502767979
435508363
420956590
487184801
416041923
Average: 452491931
Init with capacity? true
300744404
298446734
299080656
300084036
298473576
Average: 299365881
fillAndTest()之前使用
-Xms500m-Xmx500m
+
System.gc()
进行测试

Init with capacity? false
682827716
738137558
576581143
662777089
555706338
Average: 643205968
Init with capacity? true
368245589
312674836
297705054
392935762
307209139
Average: 335754076
Init with capacity? false
502767979
435508363
420956590
487184801
416041923
Average: 452491931
Init with capacity? true
300744404
298446734
299080656
300084036
298473576
Average: 299365881

如果您以相反的顺序运行测试(即,首先使用初始容量,然后不使用初始容量),会发生什么情况。您需要运行它5次以上的迭代才能进行合理的度量……对Java代码进行基准测试是很困难的。请看一下@Andremoniy,我建议您将您的问题重新表述为“为什么我在使用初始容量时看到16%的回归”,而不是“嘿,使用初始容量较慢,为什么?”。我认为这是一个有趣的问题(我可以复制,我的机器似乎没有你的那么快,但我仍然看到16%的差异。)我敢打赌,当一个真正知道发生了什么的人站出来,给你的问题一个体面的答案时,我们都会在这里学到一些东西,(可能与微观基准测试有关,而非ArrayList问题).@Andremoniy。我只是用100次迭代来运行它,而不是用5次迭代:用init假平均值:423499262,用init真平均值:177595371,所以用初始容量它要快2倍。你不能只使用几次迭代,尤其是在这5次迭代中你有这么多值的情况下。@Andremoniy肯定是这样。你采取的步骤越多,难道不有趣吗要从混合中消除堆分配/gc,性能在使用和不使用init容量进行构造之间就越接近?这证明了将阵列容量动态增加1.5的魔力。