如何抑制在 jmh 基准测试中打印到控制台的方法的输出?

问题描述

我正在使用 jmh 来比较在控制台打印大量内容的几种方法的性能。事实上,这些是 fizzbazz 问题的不同解决方案。

fizzbuzz 的每个实现都是一个类,它实现了 FizzBazz 接口并有一个 print() 方法。所有这些实现都被编译到一个单独的 jar 中。

我试图在我的基准测试中抑制此方法的输出。因此,我需要在运行基准测试之前用数组替换输出流,并在完成后将其返回。

如果我在每个基准方法中都这样做,就像这样:

@Benchmark
public void naiveTest() {
    PrintStream originalOut = System.out;
    ByteArrayOutputStream outContent = new ByteArrayOutputStream();
    System.setOut(new PrintStream(outContent));

    new NaiveFizzBuzz().print(N); // N is upper limit
    
    System.setOut(originalOut);
}

然后一切正常。但这是一堆重复的代码,我不想摆脱它。此外,这段代码会破坏测量,因为每次运行测试时都会调用它。

我正在尝试使用 state 来完成我的任务。

@State(Scope.Benchmark)
public static class MyState {
    private PrintStream originalOut;

    @Setup
    public void doSetup() {
        originalOut = System.out;
        ByteArrayOutputStream outContent = new ByteArrayOutputStream();
        System.setOut(new PrintStream(outContent));
    }

    @TearDown
    public void doTearDown() {
        System.setOut(originalOut);
    }
}

我的基准是这样的:

@Benchmark
public void naiveTest() {
    new NaiveFizzBuzz().print(N);
}

// Lots of similar benchmarks here...

但它不起作用。

如何将用于替换输出流的所有代码放在一个地方,以便在每次测试运行之前自动执行?

解决方法

我找到了解决问题的方法。事实上,我需要将我的状态对象作为参数传递给每个基准。

@Benchmark
public void naiveTest(MyState state) {
    new NaiveFizzBuzz().print(N);
}

完全按照我的需要工作。

很遗憾,jmh 的文档不是很人性化,所以我花了一段时间才找到这一点。

我做了一些研究,得出的结论是可以回答我自己的问题。如果不是这种情况,请纠正我。然后我会编辑问题。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...