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

标签 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(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然后我得到

it: 792771504 array: 1109215387 diff: 0.7147137637029551

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

it: 32365742 array: 28902811 diff: 1.1198129482976587

波动很大。 diff 参数在 0.7 到 1.2 之间的任何地方

任何人都可以阐明这里可能发生的事情吗?我应该选择哪种方法?

编辑:

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

最佳答案

由于您想测试使用 Iterator 和使用增强的 for 循环(它在幕后为您使用 Iterator)之间的区别,那么您做错了.首先是因为 JIT 有足够的时间改进第二种方法的结果而不是第一种方法的结果,这里解释了其他几个原因:How do I write a correct micro-benchmark in Java? .通过执行这些操作(同样是 JIT 的结果),您会看到非常不同的结果:

  • 添加一个循环,增加执行两次迭代的次数。这是一个涵盖所有这些代码的 for 循环。
  • 将增强的 for 循环方法移动到之前执行。

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

基准测试的相关问答:

关于java - 这个 Java 基准测试发生了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25465881/

相关文章:

java - 字符串拆分,过滤和加入单行 java 8

java - UnsatisfiedLinkError 在 Java 中使用 swig

sql - 如何提高最后一天计数查询性能

c - 如何用 C 创建迷你基准程序

java - JMH - Neo4j 基准测试

python - 使用 atlas 和 openblas 对 numpy 进行基准测试时出现奇怪的结果

java - Java 中的 "Invalid declaration method"

java - 我应该如何添加 onBlockActivated 事件来激活我的 MC Mod 中的图 block 实体? (锻造 MC 1.11.2

php - 在 MYSQL 中查询或使用 PHP 逻辑更快

javascript - Google 的 Dart 如何获得更好的性能?