Jmh 为什么我需要黑洞
我试图理解为什么使用Jmh 为什么我需要黑洞,jmh,blackhole,Jmh,Blackhole,我试图理解为什么使用Blackhole.consumerCPU()是明智的 我在谷歌--> 有时,当我们跨多个线程运行基准测试时,我们也会 想在运行我们的系统时消耗一些cpu周期来模拟cpu业务吗 代码。这不可能是线程。睡眠,因为我们真的想消耗cpu。这个 Blackhole.consumerCPU(long)为我们提供了这样做的能力 我的示例代码: import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations
Blackhole.consumerCPU()
是明智的
我在谷歌-->
有时,当我们跨多个线程运行基准测试时,我们也会
想在运行我们的系统时消耗一些cpu周期来模拟cpu业务吗
代码。这不可能是线程。睡眠,因为我们真的想消耗cpu。这个
Blackhole.consumerCPU(long)为我们提供了这样做的能力
我的示例代码:
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
@State(Scope.Thread)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class StringConcatAvgBenchmark {
StringBuilder stringBuilder1;
StringBuilder stringBuilder2;
StringBuffer stringBuffer1;
StringBuffer stringBuffer2;
String string1;
String string2;
/*
* re-initializing the value after every iteration
*/
@Setup(Level.Iteration)
public void init() {
stringBuilder1 = new StringBuilder("foo");
stringBuilder2 = new StringBuilder("bar");
stringBuffer1 = new StringBuffer("foo");
stringBuffer2 = new StringBuffer("bar");
string1 = new String("foo");
string2 = new String("bar");
}
@Benchmark
@Warmup(iterations = 10)
@Measurement(iterations = 100)
@BenchmarkMode(Mode.AverageTime)
public StringBuilder stringBuilder() {
// operation is very thin and so consuming some CPU
Blackhole.consumeCPU(100);
return stringBuilder1.append(stringBuilder2);
// to avoid dead code optimization returning the value
}
@Benchmark
@Warmup(iterations = 10)
@Measurement(iterations = 100)
@BenchmarkMode(Mode.AverageTime)
public StringBuffer stringBuffer() {
Blackhole.consumeCPU(100);
// to avoid dead code optimization returning the value
return stringBuffer1.append(stringBuffer2);
}
@Benchmark
@Warmup(iterations = 10)
@Measurement(iterations = 100)
@BenchmarkMode(Mode.AverageTime)
public String stringPlus() {
Blackhole.consumeCPU(100);
return string1 + string2;
}
@Benchmark
@Warmup(iterations = 10)
@Measurement(iterations = 100)
@BenchmarkMode(Mode.AverageTime)
public String stringConcat() {
Blackhole.consumeCPU(100);
// to avoid dead code optimization returning the value
return string1.concat(string2);
}
public static void main(String[] args) throws RunnerException {
Options options = new OptionsBuilder()
.include(StringConcatAvgBenchmark.class.getSimpleName())
.threads(1).forks(1).shouldFailOnError(true).shouldDoGC(true)
.jvmArgs("-server").build();
new Runner(options).run();
}
}
为什么使用blackhole.consumerCPU(100)
这个基准测试的结果会更好
编辑:
使用黑洞输出。消耗CPU(100):
输出无黑洞。消耗CPU(100):
我的问题是,为什么这段代码的作者在这里使用blackhole.consumerCPU(100)
我想我现在知道为什么了,因为基准太快了,没有任何延迟
使用blackhole.consumerCPU(100)
可以更好地测量每个基准,并获得更重要的结果
是吗?添加人工延迟通常不会改善基准 但是,在某些情况下,您正在测量的操作正在争夺一些资源,您需要一个只消耗CPU的退避,希望不做其他事情。例如,参见以下案例: 原始问题中的基准并非如此,因此我推测黑洞的使用没有很好的理由,或者至少在评论中没有特别提到这个理由。不要那样做。定义“更好”?我看不出你的问题有什么可比性。
Benchmark Mode Cnt Score Error Units
StringBenchmark.stringBuffer avgt 10 398,843 ± 38,666 ns/op
StringBenchmark.stringBuilder avgt 10 387,543 ± 40,087 ns/op
StringBenchmark.stringConcat avgt 10 410,256 ± 33,194 ns/op
StringBenchmark.stringPlus avgt 10 386,472 ± 21,704 ns/op
Benchmark Mode Cnt Score Error Units
StringBenchmark.stringBuffer avgt 10 51,225 ± 19,254 ns/op
StringBenchmark.stringBuilder avgt 10 49,548 ± 4,126 ns/op
StringBenchmark.stringConcat avgt 10 50,373 ± 1,408 ns/op
StringBenchmark.stringPlus avgt 10 87,942 ± 1,701 ns/op