对于我的一门大学课程,我需要实现一个无锁的堆栈实现,并对其执行基准测试,以查看它在线程数和操作分配方面如何扩展。我最近发现了JMH,并想将其应用于作业分配的基准测试部分。我只是不确定我是否会尽可能优雅地实现这一点。
我的教授希望我们测量1、2、4、8、16和32个线程执行3种不同操作分布所花费的时间。我在下面建模:
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);
// ...
}
}
}
每种情况A,B和C都有一种operations()
方法,该方法定义了一组具有特定频率pop()
,push()
和{{1} }电话。抽象的Scenario类是这些特定方案的“模板”。假设注解是可继承的(似乎是这种情况–尽管不介意有人对此进行检查),我希望这三个具体的Scenario类的实例的作用域为单个线程(即size()
),并使其@State(Scope.Thread)
方法在每次调用基准方法(即setup()
)之前运行。这样,我就可以在开始运行线程之前对每个方案的线程进行构造和设置。
此实现有任何问题吗? JMH中是否还有其他设施可以使此问题更易于解决/实施?谢谢!