JMH - 奇怪的基准测试结果

6
我正在使用JMH来测试DOM解析器的性能。我得到了非常奇怪的结果,因为第一次迭代实际上比后面的迭代运行得更快。 enter image description here enter image description here 有人能解释一下这是为什么吗?还有,百分位数和所有数字的含义是什么,为什么在第三次迭代后开始变得稳定?一个迭代是否意味着整个基准测试方法的一次迭代?以下是我正在运行的方法:
@Benchmark 
@BenchmarkMode(Mode.SingleShotTime) 
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 13, time = 1, timeUnit = TimeUnit.MILLISECONDS)
public void testMethod_no_attr() {
    try {
        File fXmlFile = new File("500000-6.xml");
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        Document doc = dBuilder.parse(fXmlFile);
    } catch (Exception  e) {
        e.printStackTrace();  
    }
}

1
这些不是迭代,而是百分位数 - p(50.0000) - 2608.183 ms/op 表示跟踪操作中有50%在2608.183毫秒或更早时完成,p(99.9999) - 2978.871 ms/op 表示99.9999%的操作在2978.871毫秒内完成(当然包括所有较小百分位数的操作)。 - Ole
2个回答

2
这些百分位数极易误导人,不要使用它们。如果您有N = 10,那么所有底部值都相同就不足为奇了。因为您的样本数量太少,无法谈论99.999%分位数之类的任何内容。这里我实际考虑的唯一值是中位数(50%分位数),以及最终的四分位距(IQR)。如果您持乐观态度,可以假设最慢的样本处于95%位置。如果您不太乐观,请将N = 10的最慢样本视为90%分位数。如果您对这些估计更加认真,您可以将间距视为约为1 / sqrt(N-1)的指示性,即假设高达33%的运行将比N = 10的最慢样本更慢。需要更多的样本来缩小这些估计范围!超过95%的任何事情都只是推测。99%-您无法回答那里发生了什么。您没有足够的数据。根据数据呈现,这些值完全是胡扯。基于数据,您无法估算P(99,9999)= something。这个数字对应于一百万次运行中有一个更糟的结果。但是您只进行了10次运行,不要使用这个很小的N来预测如果您有一百万次运行会发生什么。JMH不应为小N打印这些极端分位数。

1
你的截图缺少直方图输出。 你看到的只是直方图的百分位数
检查这个例子。我们有100次迭代,方法BoolArrayVsBitSetBenchmark#primitive的结果是:
Result "de.jawb.jmh.benchmark.example.bool.BoolArrayVsBitSetBenchmark.primitive":
  N = 100
  mean =      0,493 ±(99.9%) 0,003 s/op

  Histogram, s/op:
    [0,490, 0,495) = 93
    [0,495, 0,500) = 3
    [0,500, 0,505) = 1
    [0,505, 0,510) = 1
    [0,510, 0,515) = 0
    [0,515, 0,520) = 0
    [0,520, 0,525) = 1
    [0,525, 0,530) = 0
    [0,530, 0,535) = 0
    [0,535, 0,540) = 0
    [0,540, 0,545) = 0
    [0,545, 0,550) = 0
    [0,550, 0,555) = 0
    [0,555, 0,560) = 1

  Percentiles, s/op:
      p(0,0000) =      0,490 s/op 
     p(50,0000) =      0,491 s/op
     p(90,0000) =      0,494 s/op
     p(95,0000) =      0,496 s/op
     p(99,0000) =      0,558 s/op
     p(99,9000) =      0,559 s/op
     p(99,9900) =      0,559 s/op
     p(99,9990) =      0,559 s/op
     p(99,9999) =      0,559 s/op
    p(100,0000) =      0,559 s/op

第一个直方图线条 [0,490, 0,495) = 93 表示有 93 次调用属于组 最大时间为 0.490 秒最小时间为 0.494 秒。注意括号“)”。
总之,这意味着没有比 0.491 秒/操作更快的调用,因为

p(0,0000) = 0.490 s/op

最大执行时间为 0.559 秒/操作,因为

p(100,0000) = 0.559 s/op


谢谢。更新了直方图。不过,这些值 [0,005, 0,005) = 14 是什么意思? - Tri Nguyen
我已经更新了我的示例。执行现在需要更长的时间。正如您所看到的[0.005,0.005)= 14的含义。14个调用最多需要0.005秒。 - dieter
谢谢。热身迭代是什么意思?它们为什么不同? - Tri Nguyen
@TriNguyen 预热是触发JIT优化、加载/初始化缓存、创建线程等必要的步骤。 - dieter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接