Случайные пики в итерациях JMH Benchmark - PullRequest
2 голосов
/ 12 июня 2019

Я пытаюсь протестировать очень быстрый метод (~ 20 us / op), и он, кажется, работает очень хорошо, за исключением нескольких итераций, которые случайным образом очень длинные :

Iteration  63: 14.319 us/op
Iteration  64: 13.128 us/op
Iteration  65: 15.198 us/op
Iteration  66: 20.822 us/op
Iteration  67: 21.669 us/op
Iteration  68: 21.439 us/op
Iteration  69: 15.946 us/op
Iteration  70: 18.793 us/op
Iteration  71: 19.212 us/op
Iteration  72: 816.129 us/op  // oopsy
Iteration  73: 22.115 us/op
Iteration  74: 15.143 us/op
Iteration  75: 18.423 us/op
Iteration  76: 15.238 us/op

Result "benchmark.StuffBench.run_bench":
  20.629 ±(99.9%) 9.164 us/op [Average]
  (min, avg, max) = (12.689, 20.629, 816.129), stdev = 47.763
  CI (99.9%): [11.464, 29.793] (assumes normal distribution)

Это может быть GC, но shouldDoGc(false) ничего не меняет:

final Options options = new OptionsBuilder()
                .include(StuffBench.class.getSimpleName())
                .shouldDoGC(false)
                .build();
Collection<RunResult> runResults = new Runner(options).run();

Класс теста:

@Fork(value = 2)
@Threads(1)
@Warmup(iterations = 1000, time = 50, timeUnit = TimeUnit.MICROSECONDS)
@Measurement(iterations = 150, time = 50, timeUnit = TimeUnit.MICROSECONDS)
@Timeout(time = 50, timeUnit = TimeUnit.MICROSECONDS)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@BenchmarkMode(Mode.AverageTime)
@State(Scope.Benchmark)
public class StuffBench {
    private Stuff stuff;

    @Setup
    public void initialize() {
        stuff = new Stuff();
    }

    @Benchmark
    public void run_bench() {
        stuff.run();
    }
}

1 Ответ

0 голосов
/ 12 июня 2019

Чтобы решить эту проблему, я использовал то, что я называю джиттер-сэмплером. У вас есть один поток, устанавливающий метку времени, запускающий код, сбрасывающий метку времени и паузы, чтобы не перегружать процессор. Второй поток выбирает отметку времени, и если она активна и была слишком длинной, например, 20 нам, вы распечатываете следы того, что он делает. например Thread.getStackTrace () Объедините наиболее распространенные трассировки стека, и у вас есть безопасная точка, которая может указывать на проблему (или первая безопасная точка после проблемы). Это немного больше, чем наука;)

...