这个java基准测试中发生了什么?

这个java基准测试中发生了什么?,java,performance,benchmarking,Java,Performance,Benchmarking,我使用junit运行一个基本的基准测试,如下所示: @Test public void testTime() throws Exception{ LoadoutBase<?> loadout = new LoadoutStandard("AS7-D-DC"); final int iterations = 1000000; long start = System.nanoTime(); int sum = 0; for(

我使用junit运行一个基本的基准测试,如下所示:

@Test
public void testTime() throws Exception{
    LoadoutBase<?> loadout = new LoadoutStandard("AS7-D-DC");

    final int iterations = 1000000;

    long start = System.nanoTime();
    int sum = 0;
    for(int i = 0; i < iterations; ++i){
        Iterator<Item> it = loadout.iterator();
        while( it.hasNext() ){
            sum += it.next().getNumCriticalSlots();
        }
    }
    long end = System.nanoTime();

    long time_it = end - start;

    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        for(Item item : loadout.getAllItems()){
            sum += item.getNumCriticalSlots();
        }
    }
    end = System.nanoTime();

    long time_arrays = end - start;
  
    System.out.println("it: " + time_it + " array: " + time_arrays + " diff: " + (double)time_it/time_arrays);
}
@Test
public void testTime() throws Exception{

    LoadoutBase<?> loadout = new LoadoutStandard("AS7-D-DC");

    long start, end, sum;
    final int iterations = 10000;

    //WARMUP
    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        Iterator<Item> it = loadout.iterator();
        while( it.hasNext() ){
            sum += it.next().getNumCriticalSlots();
        }
    }
    end = System.nanoTime();
    //ENDOF WARMUP

    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        Iterator<Item> it = loadout.iterator();
        while( it.hasNext() ){
            sum += it.next().getNumCriticalSlots();
        }
    }
    end = System.nanoTime();
    long time_it = end - start;


    // WARMUP
    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        for(Item item : loadout.getAllItems()){
            sum += item.getNumCriticalSlots();
        }
    }
    end = System.nanoTime();
    // ENDOF WARMUP


    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        for(Item item : loadout.getAllItems()){
            sum += item.getNumCriticalSlots();
        }
    }
    end = System.nanoTime();
    long time_arrays = end - start;

    System.out.println("it: " + time_it + " array: " + time_arrays + " diff: " + (double)time_it/time_arrays);
}
@测试
public void testTime()引发异常{
装船基地装船=新的装船标准(“AS7-D-DC”);
最终整数迭代=1000000;
长启动=System.nanoTime();
整数和=0;
对于(int i=0;i
如果我设置
iterations=1000000
,那么我得到

it:792771504阵列:1109215387差异:0.7147137637029551

非常一致,但如果我设置
iterations=10000
,那么

it:32365742阵列:28902811差异:1.1198129482976587

波动很大。差异参数在0.7到1.2之间

有人能解释一下这里可能发生的事情吗?我应该选择哪种方法

编辑:
我真正的基准是幕后工作
getAllItems
创建一个新的
列表
,并通过使用
addAll
从16个子列表中获取所有项目来填充它。
迭代器
方法不构造这个临时列表,而是跟踪它当前在这16个子列表中的哪个子列表中进行迭代,并且有一些逻辑使这16个子列表看起来像一个连续列表。

因为您想测试使用
迭代器
和使用增强for循环之间的区别(它在幕后为您使用了迭代器),那么您就做错了。首先,因为JIT有足够的时间改进第二种方法的结果,而不是第一种方法的结果,这里解释了几个其他原因:。您可以通过这样做看到非常不同的结果(同样,作为JIT的结果):

  • 添加一个循环,该循环将增加执行两次迭代的次数。这是一个覆盖所有这些代码的
    for
    循环
  • 将增强的
    移动到要在之前执行的
    循环方法
为您的测试获得真实结果的最佳方法是将这些方法分成不同的方法,然后对每种方法进行测量(除了JVM预热阶段和前面QA中介绍的其他内容)。此外,我建议您不要重新发明轮子,使用基于JUnit的适当基准框架。以下是其中两种:

基准测试的相关Q/A:


因为您想测试使用<代码>迭代器
和使用增强for循环(在幕后为您使用<代码>迭代器
)之间的区别,那么您就做错了。首先,因为JIT有足够的时间改进第二种方法的结果,而不是第一种方法的结果,以及这里解释的其他几个原因:。您可以通过执行以下操作(同样,作为JIT的结果)看到非常不同的结果:

  • 添加一个循环,该循环将增加执行两次迭代的次数。这是一个覆盖所有这些代码的
    for
    循环
  • 将增强的
    移动到要在之前执行的
    循环方法
为您的测试获得真实结果的最佳方法是将这些方法分成不同的方法,然后对每种方法进行测量(除了JVM预热阶段和前面QA中介绍的其他内容)。此外,我建议您不要重新发明轮子,使用基于JUnit的适当基准框架。以下是其中两种:

基准测试的相关Q/A:


阅读了Luiggi Mendoza的链接后,我重构了测试代码,如下所示:

@Test
public void testTime() throws Exception{
    LoadoutBase<?> loadout = new LoadoutStandard("AS7-D-DC");

    final int iterations = 1000000;

    long start = System.nanoTime();
    int sum = 0;
    for(int i = 0; i < iterations; ++i){
        Iterator<Item> it = loadout.iterator();
        while( it.hasNext() ){
            sum += it.next().getNumCriticalSlots();
        }
    }
    long end = System.nanoTime();

    long time_it = end - start;

    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        for(Item item : loadout.getAllItems()){
            sum += item.getNumCriticalSlots();
        }
    }
    end = System.nanoTime();

    long time_arrays = end - start;
  
    System.out.println("it: " + time_it + " array: " + time_arrays + " diff: " + (double)time_it/time_arrays);
}
@Test
public void testTime() throws Exception{

    LoadoutBase<?> loadout = new LoadoutStandard("AS7-D-DC");

    long start, end, sum;
    final int iterations = 10000;

    //WARMUP
    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        Iterator<Item> it = loadout.iterator();
        while( it.hasNext() ){
            sum += it.next().getNumCriticalSlots();
        }
    }
    end = System.nanoTime();
    //ENDOF WARMUP

    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        Iterator<Item> it = loadout.iterator();
        while( it.hasNext() ){
            sum += it.next().getNumCriticalSlots();
        }
    }
    end = System.nanoTime();
    long time_it = end - start;


    // WARMUP
    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        for(Item item : loadout.getAllItems()){
            sum += item.getNumCriticalSlots();
        }
    }
    end = System.nanoTime();
    // ENDOF WARMUP


    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        for(Item item : loadout.getAllItems()){
            sum += item.getNumCriticalSlots();
        }
    }
    end = System.nanoTime();
    long time_arrays = end - start;

    System.out.println("it: " + time_it + " array: " + time_arrays + " diff: " + (double)time_it/time_arrays);
}
@测试
public void testTime()引发异常{
装船基地装船=新的装船标准(“AS7-D-DC”);
长起点、终点、总和;
最终整数迭代=10000;
//热身
start=System.nanoTime();
总和=0;
对于(int i=0;i
现在,我得到了一致的结果,即迭代器方法的执行速度大约是
getAllItems
方法的0.7倍。即使我更改了测试顺序,结果也是一致的,因此我相信他们会执行此测试


谢谢。

在阅读了Luiggi Mendoza的链接后,我重构了我的测试代码,如下所示:

@Test
public void testTime() throws Exception{
    LoadoutBase<?> loadout = new LoadoutStandard("AS7-D-DC");

    final int iterations = 1000000;

    long start = System.nanoTime();
    int sum = 0;
    for(int i = 0; i < iterations; ++i){
        Iterator<Item> it = loadout.iterator();
        while( it.hasNext() ){
            sum += it.next().getNumCriticalSlots();
        }
    }
    long end = System.nanoTime();

    long time_it = end - start;

    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        for(Item item : loadout.getAllItems()){
            sum += item.getNumCriticalSlots();
        }
    }
    end = System.nanoTime();

    long time_arrays = end - start;
  
    System.out.println("it: " + time_it + " array: " + time_arrays + " diff: " + (double)time_it/time_arrays);
}
@Test
public void testTime() throws Exception{

    LoadoutBase<?> loadout = new LoadoutStandard("AS7-D-DC");

    long start, end, sum;
    final int iterations = 10000;

    //WARMUP
    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        Iterator<Item> it = loadout.iterator();
        while( it.hasNext() ){
            sum += it.next().getNumCriticalSlots();
        }
    }
    end = System.nanoTime();
    //ENDOF WARMUP

    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        Iterator<Item> it = loadout.iterator();
        while( it.hasNext() ){
            sum += it.next().getNumCriticalSlots();
        }
    }
    end = System.nanoTime();
    long time_it = end - start;


    // WARMUP
    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        for(Item item : loadout.getAllItems()){
            sum += item.getNumCriticalSlots();
        }
    }
    end = System.nanoTime();
    // ENDOF WARMUP


    start = System.nanoTime();
    sum = 0;
    for(int i = 0; i < iterations; ++i){
        for(Item item : loadout.getAllItems()){
            sum += item.getNumCriticalSlots();
        }
    }
    end = System.nanoTime();
    long time_arrays = end - start;

    System.out.println("it: " + time_it + " array: " + time_arrays + " diff: " + (double)time_it/time_arrays);
}
@测试
public void testTime()引发异常{
装船基地装船=新的装船标准(“AS7-D-DC”);
长起点、终点、总和;
决赛