问题描述
我正在使用 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 的文档不是很人性化,所以我花了一段时间才找到这一点。
我做了一些研究,得出的结论是可以回答我自己的问题。如果不是这种情况,请纠正我。然后我会编辑问题。