JMH超时不会中断执行

4

在尝试使用JMH处理超时时,我发现没有任何超时导致中断。 我可以将问题简化为以下几行:

package main.java;

import org.openjdk.jmh.Main;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.RunnerException;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class TimeoutBenchmark {
    public static void main(String... args) throws IOException, RunnerException {
        Main.main(args);
    }

    @Benchmark
    @BenchmarkMode(Mode.AverageTime)
    @Warmup(iterations = 0)
    @Timeout(time = 10, timeUnit = TimeUnit.SECONDS)
    public long benchmark() throws InterruptedException {
        Thread.sleep(20000);
        return 0;
    }
}

由于Thread.sleep处理中断,我期望每次迭代运行10秒,而不是20秒。然而,情况并非如此:

# JMH version: 1.20
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: C:\Program Files\Java\jdk1.8.0_144\jre\bin\java.exe
# VM options: -Dfile.encoding=UTF-8
# Warmup: <none>
# Measurement: 20 iterations, 1 s each
# Timeout: 10 s per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Average time, time/op
# Benchmark: main.java.TimeoutBenchmark.benchmark

# Run progress: 0,00% complete, ETA 00:03:20
# Fork: 1 of 10
Iteration   1: 20,004 s/op
Iteration   2: 20,009 s/op
Iteration   3: 20,009 s/op
Iteration   4: 20,014 s/op
Iteration   5: 20,003 s/op
Iteration   6: 20,003 s/op
Iteration   7: 20,003 s/op

为什么会这样?如何更改代码,使得每次迭代在10秒后实际中断?

有趣的是,我发现了http://mail.openjdk.java.net/pipermail/jmh-dev/2015-May/001912.html,但它仍然表示应该至少有一个中断。尝试使用不同的版本,但并非所有版本都有效... - Ruslan Akhundov
1个回答

3
BenchmarkHandler中处理超时时,有一段代码中包含注释。
    // now we communicate all worker threads should stop
    control.announceDone();

    // wait for all workers to transit to teardown
    control.awaitWarmdownReady();

    // Wait for the result, handling timeouts
    while (completed.size() < numThreads) {
基本上,此超时仅适用于teardown阶段。但是我认为应该在此注释的javadoc中加入此信息。 Teardown在此处进行了描述:http://java-performance.info/jmh/ 此邮件也可能有用:http://mail.openjdk.java.net/pipermail/jmh-dev/2015-May/001912.html

1
可能是一个bug。如果您更改这些方法被调用的顺序(超时检查和awaitWarmdownReady()),超时就能正常工作。 - Cargeh
感谢您的信息!根据@Cargeh的建议,更改方法调用的顺序解决了问题。我改变了顺序并修补了jmh jar。 - Philipp F

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