这个Java基准测试中发生了什么? [英] What is going on in this java benchmark?

查看:41
本文介绍了这个Java基准测试中发生了什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用junit运行原始基准测试,如下所示:

I'm using junit to run a primitive benchmark like this:

@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);
}

如果我设置iterations=1000000,我会得到

它:792771504数组:1109215387差异:0.7147137637029551

it: 792771504 array: 1109215387 diff: 0.7147137637029551

非常一致,但是如果我设置iterations=10000,我会得到

very consistently but if I set iterations=10000 then I get

它:32365742数组:28902811差异:1.1198129482976587

it: 32365742 array: 28902811 diff: 1.1198129482976587

波动很大. diff参数的范围是0.7到1.2

with very wild fluctuations. The diff parameters is anywhere from 0.7 to 1.2

任何人都可以对这里可能发生的事情有所了解吗?我应该选择哪种方法?

Could any one shed some light on what might be happening here? Which method should I choose?

我真正进行基准测试的是幕后工作. getAllItems创建一个新的List<Item>并通过使用addAll从16个子列表中获取所有项目来填充它. Iterator方法不是构造此临时列表,而是跟踪它当前在这16个子列表中的哪个列表中进行迭代,并具有使该16个子列表看起来像连续列表的逻辑.

What I really am benchmarking is behind the scenes work. getAllItems creates a new List<Item> and populates it by getting all items from 16 sublists using addAll. The Iterator approach doesn't construct this temporary list but rather keeps track of in which of these 16 sublists it is currently iterating and has some logic to make the 16 sublists look like a continuous list.

推荐答案

由于您要测试使用Iterator和使用增强的for循环(在幕后使用Iterator)之间的区别,因此您需要重新做错了.首先是因为JIT有足够的时间来改进第二种方法的结果,而不是第一种方法,这里解释了以下几个其他原因:我该怎么写Java中正确的微基准?.通过执行以下操作,您可能会看到非常不同的结果(同样是JIT的结果):

Since you want to test the difference between using Iterator and using enhanced for loop (which uses Iterator behind the scenes for you), then you're doing it wrong. First because JIT has enough time to improve the results on the second approach rather than in the first and several other reasons explained here: How do I write a correct micro-benchmark in Java?. You could see very different results of this by doing these (again, as result of JIT):

  • 添加一个循环,该循环将增加执行两次迭代的次数.这是一个覆盖所有这些代码的for循环.
  • 移动增强的for循环方法,使其在之前执行.
  • Add a loop that will increase the number of times to execute both iterations. This is, a for loop that covers all this code.
  • Moving the enhanced for loop approach to be executed before.

获得测试真实结果的最佳方法是将这些方法分为不同的方法,然后进行每种方法的评估(除了JVM预热阶段和上一QA涵盖的其他内容之外).另外,我建议您不要重新发明轮子,而应使用基于JUnit的适当基准测试框架.这是其中两个:

The best way to obtain real results for your test would be to split the approaches into different methods, then measure each (apart from the JVM warm up phase and other stuff covered in prev QA). Also, I recommend you to not reinvent the wheel and use a proper benchmark framework based on JUnit. Here are two of them:

  • JUnitBenchmarks
  • Caliper

基准测试的相关Q/A:

Related Q/As for benchmarking:

  • arraylist vs linked list .why linked list is slower when we add in the end?
  • Decreasing execution time of identical consecutive runs of a Java program

这篇关于这个Java基准测试中发生了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆