JMH-低级基准测试

发布于 2025-01-23 03:48:22 字数 1879 浏览 3 评论 0 原文

我正在使用JMH来基准JUNIT测试。

我的基准:

import org.openjdk.jmh.annotations.*;

public class Benchmarks {
        @Benchmark
        public void bmUnitTest1() {
                UnitTests.UnitTest1();
        }

        @Benchmark
        public void bmUnitTest2() {
                UnitTests.UnitTest2();
        }
}

我的基准跑者:

import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.results.format.ResultFormatType;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.TimeValue;

import java.util.concurrent.TimeUnit;

public class BenchmarkRunner {
    public static void main(String[] args) throws Exception {
        Options opt = new OptionsBuilder()
                .include(Benchmarks.class.getSimpleName())
                .mode(Mode.SingleShotTime)
                .resultFormat(ResultFormatType.CSV)
                .result("target/test-classes/benchmarkcsv/BM " + System.currentTimeMillis() + ".csv")
                .timeUnit(TimeUnit.MILLISECONDS)
                .warmupIterations(3)
                .warmupTime(TimeValue.seconds(1))
                .measurementIterations(3)
                .measurementTime(TimeValue.seconds(1))
                .timeout(TimeValue.seconds(5))
                .forks(1)
                .warmupForks(1)
                .threads(1)
                .build();

        new Runner(opt).run();
    }
}

目前,我在整个单元测试中获得了性能指标。我想知道是否有可能在较低级别上看到这些性能指标。


示例:

UnitTest1具有多个函数调用。功能1所需10ms,功能2需要20m。

而不是看到这个(简化):

UnitTest1: 30ms/op

我想看看:

UnitTest1: 30ms/op
        Function1: 10ms/op
        Function2: 20ms/op

我可以在JMH中做到这一点吗?如果没有,我可以使用任何替代方法来基准Junit测试吗?

I'm using JMH to benchmark JUnit tests.

My benchmarks:

import org.openjdk.jmh.annotations.*;

public class Benchmarks {
        @Benchmark
        public void bmUnitTest1() {
                UnitTests.UnitTest1();
        }

        @Benchmark
        public void bmUnitTest2() {
                UnitTests.UnitTest2();
        }
}

My benchmark runner:

import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.results.format.ResultFormatType;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.TimeValue;

import java.util.concurrent.TimeUnit;

public class BenchmarkRunner {
    public static void main(String[] args) throws Exception {
        Options opt = new OptionsBuilder()
                .include(Benchmarks.class.getSimpleName())
                .mode(Mode.SingleShotTime)
                .resultFormat(ResultFormatType.CSV)
                .result("target/test-classes/benchmarkcsv/BM " + System.currentTimeMillis() + ".csv")
                .timeUnit(TimeUnit.MILLISECONDS)
                .warmupIterations(3)
                .warmupTime(TimeValue.seconds(1))
                .measurementIterations(3)
                .measurementTime(TimeValue.seconds(1))
                .timeout(TimeValue.seconds(5))
                .forks(1)
                .warmupForks(1)
                .threads(1)
                .build();

        new Runner(opt).run();
    }
}

Currently I'm getting performance metrics on the whole unit test. I was wondering if it's possible to see these performance metrics on a lower level.


Example:

UnitTest1 has multiple function calls. Function1 takes 10ms, Function2 takes 20ms.

Instead of seeing this (simplified):

UnitTest1: 30ms/op

I'd like to see this:

UnitTest1: 30ms/op
        Function1: 10ms/op
        Function2: 20ms/op

Can I do this in JMH? If not, are there any alternatives I could use to benchmark JUnit tests?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

甜点 2025-01-30 03:48:22

JMH有几个探查器,可以在运行基准测试时启用。参见

其中之一是 async 基于项目。它可以完全做您想要的事情 - 显示单元测试调用的方法花费大多数CPU时间(带有堆栈跟踪!)

才能启用此探测器,请调用 options builder.addprofiler(asyncprofiler.class.class,“ output = flameGraph”) /code>,或(如果从命令行运行)add -prof async:output = flamegraph option。

基准测试完成后,JMH将以.html格式生成一个探测器报告:

输出选项:

          ns  percent  samples  top
  ----------  -------  -------  ---
  1992741308   39.53%      200  java.util.stream.AbstractPipeline.copyInto
   844434060   16.75%       84  java.util.stream.StreamOpFlag.isKnown
   670418795   13.30%       67  java.lang.Integer.max
   500609106    9.93%       50  java.util.stream.AbstractPipeline.getStreamAndOpFlags
   451255844    8.95%       45  java.util.stream.AbstractPipeline.evaluate
   221004309    4.38%       22  java.util.stream.ReduceOps$7.makeSink
   140062540    2.78%       14  java.util.Spliterators$IntArraySpliterator.forEachRemaining
    60012022    1.19%        6  java.util.stream.AbstractPipeline.wrapSink
    39966227    0.79%        4  java.util.stream.ReduceOps$6ReducingSink.accept
    39348309    0.78%        4  java.util.stream.ReduceOps$ReduceOp.evaluateSequential
    10862017    0.22%        1  Dictionary::find(unsigned int, Symbol*, Handle)
    10637320    0.21%        1  ciVirtualCallTypeData::translate_from(ProfileData const*)
    10209263    0.20%        1  java.util.stream.AbstractPipeline.<init>
    10155044    0.20%        1  java.util.Spliterator$OfInt.forEachRemaining
    10128043    0.20%        1  PhaseChaitin::Register_Allocate()
    10115108    0.20%        1  _raw_spin_unlock_irqrestore_[k]
     9486501    0.19%        1  PhaseChaitin::Select()
     9281194    0.18%        1  PhaseIdealLoop::optimize(PhaseIterGVN&, LoopOptsMode)

JMH has several profilers that can be enabled while running benchmarks. See JMHSample_35_Profilers for details.

One of them is async profiler based on async-profiler project. It can do exactly what you want - show which methods called by your unit test take most CPU time (with stack traces!)

To enable this profiler, call OptionsBuilder.addProfiler(AsyncProfiler.class, "output=flamegraph"), or (if running from a command line) add -prof async:output=flamegraph option.

When benchmarking completes, JMH will generate a profiler report in .html format:

JMH profile

If you want to get a flat profile - just methods with the percentage of CPU time spent - use async profiler without output option:

          ns  percent  samples  top
  ----------  -------  -------  ---
  1992741308   39.53%      200  java.util.stream.AbstractPipeline.copyInto
   844434060   16.75%       84  java.util.stream.StreamOpFlag.isKnown
   670418795   13.30%       67  java.lang.Integer.max
   500609106    9.93%       50  java.util.stream.AbstractPipeline.getStreamAndOpFlags
   451255844    8.95%       45  java.util.stream.AbstractPipeline.evaluate
   221004309    4.38%       22  java.util.stream.ReduceOps$7.makeSink
   140062540    2.78%       14  java.util.Spliterators$IntArraySpliterator.forEachRemaining
    60012022    1.19%        6  java.util.stream.AbstractPipeline.wrapSink
    39966227    0.79%        4  java.util.stream.ReduceOps$6ReducingSink.accept
    39348309    0.78%        4  java.util.stream.ReduceOps$ReduceOp.evaluateSequential
    10862017    0.22%        1  Dictionary::find(unsigned int, Symbol*, Handle)
    10637320    0.21%        1  ciVirtualCallTypeData::translate_from(ProfileData const*)
    10209263    0.20%        1  java.util.stream.AbstractPipeline.<init>
    10155044    0.20%        1  java.util.Spliterator$OfInt.forEachRemaining
    10128043    0.20%        1  PhaseChaitin::Register_Allocate()
    10115108    0.20%        1  _raw_spin_unlock_irqrestore_[k]
     9486501    0.19%        1  PhaseChaitin::Select()
     9281194    0.18%        1  PhaseIdealLoop::optimize(PhaseIterGVN&, LoopOptsMode)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文