使用可完成的未来对方法运行基准测试

Alk*_*ris 4 java benchmarking java-8 jmh completable-future

我正在尝试衡量特定方法的性能。当直接调用该方法时,我运行基准测试得很好,但是当该方法使用带有自定义执行器的完整未来时,一切都崩溃了。我已经实现了使用可完成的未来的方法,以便在该方法花费太长时间时强制超时。

@Benchmark
@BenchmarkMode(Mode.SingleShotTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Threads(value = 5)
@Warmup(iterations = 20)
@Measurement(iterations = 50, timeUnit = TimeUnit.MILLISECONDS)
public String very_big_query(TestState testState) throws Exception {
    return testState.transpiler.process(testState.veryBigQuery);
}
Run Code Online (Sandbox Code Playgroud)
@State(Scope.Thread)
public static class TestState {
    String veryBigQuery;
    Transpiler transpiler;

    @Setup(Level.Trial)
    public void doSetupTrial() throws Exception {
        veryBigQuery = "(";
        for(int i = 0; i < 99; i++) {
            veryBigQuery += String.format("java_%s OR ", i);
        }
        veryBigQuery += "java_100) AND (";
        for(int i = 100; i < 199; i++) {
            veryBigQuery += String.format("java_%s OR ", i);
        }
        veryBigQuery += String.format("java_%s)", 200);
    }

    @Setup(Level.Invocation)
    public void doSetupInvocation() throws Exception {
        random = ThreadLocalRandom.current().nextInt(0, productionQueries.size());
        randomQuery = productionQueries.get(random);
        transpiler = new Transpiler(5, 100); //number of threads in custom pool for the executor, timeout in milliseconds
    }
}
Run Code Online (Sandbox Code Playgroud)
public String process(final String input) throws Exception {
    CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
        return SOME_STRING;
    }, executor);

    return cf.get(timeoutInMillis, TimeUnit.MILLISECONDS);
}
Run Code Online (Sandbox Code Playgroud)
this.executor = Executors.newFixedThreadPool(numberOfThreads);
Run Code Online (Sandbox Code Playgroud)

我收到这个错误

JMH已经完成,但是fork VM没有退出,是否有杂散运行线程?还要等24秒...

未完成的线程:

有人可以向我解释为什么会发生这种情况以及我该如何处理才能使其发挥作用吗?

Eug*_*ene 5

首先一定要仔细检查 的示例JMH,使用这些配置很容易搬起石头砸自己的脚(我可能每周通过 JMH 编写一次测试),但每次仍然会把事情搞砸。

Level.Invocation然后,除非你真正理解它的作用,否则就摆脱它......

最后可能会在方法中关闭执行器@TearDown