Как измерить среднее время холодного старта с JMH?

В JMH (Java Microbenchmark Harness) мы можем использовать

@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 10)
@Measurement(iterations = 10)

для оценки среднего времени выполнения после прогрева JVM.

Также мы можем использовать

@BenchmarkMode(Mode.SingleShotTime)
@Measurement(iterations = 1)

чтобы оценить время холодного старта выполнения. Но при этом тест выполняется только один раз, что может привести к смещению. Так есть ли способ оценить среднее время холодного старта в JMH?


person Thesharing    schedule 04.12.2020    source источник


Ответы (1)


По словам самого Алексея (правда, с 2014 г. ):

Одноразовые тесты изначально предназначались для выполнения одной итерации измерения на нескольких вилках - сценариев для оценки холодных характеристик. Но во многих случаях вам может потребоваться больше итераций измерения, особенно если вы используете только одну вилку, потому что будет сгенерировано больше выборок.

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class AverageSingleShot {

    public static void main(String[] args) throws Exception {
        Options opt = new OptionsBuilder()
            .include(AverageSingleShot.class.getSimpleName())
            .build();

        new Runner(opt).run();
    }

    @Fork(100)
    @Benchmark
    @BenchmarkMode(Mode.SingleShotTime)
    public int test() {
        return ThreadLocalRandom.current().nextInt() + ThreadLocalRandom.current().nextInt();
    }

}

Помимо того факта, что это покажет вам среднее (см. Это 100):

 Benchmark               Mode  Cnt      Score      Error  Units
 AverageSingleShot.test    ss  100  41173.540 ± 2871.546  ns/op
 

вы также получите Percentiles и Histogram.

person Eugene    schedule 04.12.2020
comment
Зачем измерять и разогревать 100 итераций? Разве это не контрпродуктивно? - person knittl; 05.12.2020
comment
@knittl отредактировал. Warmup действительно неверно, но Measurement может зависеть от того, что делает ваш тест. Если вы хотите измерить invokedynamic раз (что дорого при первом вызове) - вы можете быть правы, но в приведенном выше тесте C1 компилятор не оживет для 100 вызовов, поэтому я думаю, это тоже обрабатывается холодно. - person Eugene; 05.12.2020
comment
Спасибо за отличный ответ, работает! Также мне интересно, как заставить методы в одном тесте запускаться последовательно в основном потоке? - person Thesharing; 07.12.2020
comment
@Thesharing может можно отдельный вопрос задать? - person Eugene; 07.12.2020
comment
Вот отдельный вопрос: stackoverflow.com/questions/65177915/ И большое спасибо за вашу щедрую помощь. - person Thesharing; 07.12.2020