使用Java和JMH对无锁堆栈进行基准测试
在我的一门大学课程中,我被要求实现一个无锁堆栈实现,并对其执行基准测试,以了解它在线程计数和操作分布方面的伸缩性。我最近发现了JMH,我想我应该把它应用到家庭作业的基准测试部分。我只是不确定我是否尽可能优雅地实现了这一点 我的教授希望我们测量1、2、4、8、16和32个线程执行3种不同分布的操作所需的时间。我将其建模如下:使用Java和JMH对无锁堆栈进行基准测试,java,multithreading,concurrency,benchmarking,jmh,Java,Multithreading,Concurrency,Benchmarking,Jmh,在我的一门大学课程中,我被要求实现一个无锁堆栈实现,并对其执行基准测试,以了解它在线程计数和操作分布方面的伸缩性。我最近发现了JMH,我想我应该把它应用到家庭作业的基准测试部分。我只是不确定我是否尽可能优雅地实现了这一点 我的教授希望我们测量1、2、4、8、16和32个线程执行3种不同分布的操作所需的时间。我将其建模如下: package kylemart.multicore.assignment2; import org.openjdk.jmh.annotations.*; // Anno
package kylemart.multicore.assignment2;
import org.openjdk.jmh.annotations.*;
// Annotations here...
public class P1StackBenchmarks {
@Benchmark
public void runScenarioA(ScenarioA scenario) throws InterruptedException {
runThreads(scenario.threads);
}
@Benchmark
public void runScenarioB(ScenarioB scenario) throws InterruptedException {
runThreads(scenario.threads);
}
@Benchmark
public void runScenarioC(ScenarioC scenario) throws InterruptedException {
runThreads(scenario.threads);
}
private void runThreads(Thread[] threads) throws InterruptedException {
for (Thread thread : threads) {
thread.start();
}
for (Thread thread : threads) {
thread.join();
}
}
@State(Scope.Benchmark)
public static class BenchmarkParameters {
@Param({"1", "2", "4", "8", "16", "32"})
int threadCount;
static final int iterations = 500_000;
}
@State(Scope.Thread)
public static abstract class Scenario {
Thread[] threads;
PStack<Object> stack;
Object object;
@Setup(Level.Invocation)
public void setup(BenchmarkParameters params) {
threads = new Thread[params.threadCount];
stack = new P1Stack<>();
object = new Object();
Runnable runnable = () -> {
for (int iteration = 0; iteration < params.iterations; iteration++) {
operations();
}
};
for (int index = 0; index < threads.length; index++) {
threads[index] = new Thread(runnable);
}
}
protected abstract void operations();
}
public static class ScenarioA extends Scenario {
@Override
protected void operations() {
// stack.push(object);
// ...
}
}
public static class ScenarioB extends Scenario {
@Override
protected void operations() {
// stack.push(object);
// ...
}
}
public static class ScenarioC extends Scenario {
@Override
protected void operations() {
// stack.push(object);
// ...
}
}
}
包kylemart.multicore.assignment2;
导入org.openjdk.jmh.annotations.*;
//这里的注释。。。
公共类基准{
@基准
public void runScenarioA(ScenarioA场景)引发InterruptedException{
运行线程(scenario.threads);
}
@基准
public void runScenarioB(ScenarioB场景)引发中断异常{
运行线程(scenario.threads);
}
@基准
public void runScenarioC(场景场景)抛出InterruptedException{
运行线程(scenario.threads);
}
私有void运行线程(线程[]线程)引发InterruptedException{
用于(线程:线程){
thread.start();
}
用于(线程:线程){
thread.join();
}
}
@国家(范围、基准)
公共静态类基准参数{
@参数({“1”、“2”、“4”、“8”、“16”、“32”})
int线程数;
静态最终整数迭代=500_000;
}
@状态(Scope.Thread)
公共静态抽象类场景{
线程[]线程;
PStack堆栈;
对象对象;
@设置(级别调用)
公共无效设置(基准参数参数){
线程=新线程[params.threadCount];
stack=新的P1Stack();
对象=新对象();
Runnable Runnable=()->{
for(int iteration=0;iteration
每个场景A、B和C都有一个operations()
方法,该方法定义了一组堆栈操作,其特定频率为pop()
、push()
和size()
调用。抽象场景类是这些特定场景的“模板”。假设注释是可继承的(这似乎是事实——不介意有人对此进行事实检查),我希望这三个具体场景类的实例的作用域是单个线程(即@State(Scope.Thread)
),并具有其设置()
方法在每次调用基准方法之前运行(即@Setup(Level.invocation)
)。通过这样做,我能够在开始运行线程之前构建和设置每个场景的线程
这个实现有什么问题吗?JMH是否有其他设施使该问题更容易解决/实施?谢谢 如果您要求对代码进行审查,那么适当的站点是