Тайм-аут JMH не прерывается

Пытаясь работать с тайм-аутами в 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 секунд?


person Philipp F    schedule 24.04.2018    source источник
comment
интересно, я обнаружил, что mail.openjdk.java.net /pipermail/jmh-dev/2015-May/001912.html , однако это все еще говорит о том, что по крайней мере должно быть прерывание. Пробовал разные версии, не во всех работает...   -  person Ruslan Akhundov    schedule 24.04.2018


Ответы (1)


в 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 для этой аннотации должен быть дополнен этой информацией.

Разборка описана здесь: http://java-performance.info/jmh/

Также может быть полезна эта почта: http://mail.openjdk.java.net/pipermail/jmh-dev/2015-May/001912.html

person Ruslan Akhundov    schedule 24.04.2018
comment
Хотя может быть баг. Если вы измените порядок вызова этих методов (проверка тайм-аута и awaitWarmdownReady()), тайм-аут работает нормально. - person Cargeh; 24.04.2018
comment
Спасибо за информацию! Как предложил @Cargeh, изменение порядка вызовов методов помогло. Я изменил порядок и пропатчил банку jmh. - person Philipp F; 29.04.2018