JMH中的非对称基准测试

3
我正在使用JMH对自定义集合实现进行性能测试。
我想模拟这样的场景,其中读取次数比写入次数多10倍。
我使用了this不对称基准测试示例,并创建了一个包含10个读取线程和1个写入线程的组。
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Group("g0")
@GroupThreads(1)       
public void baselinePut0(CacheState0 state) { writing }

@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Group("g0")
@GroupThreads(10)
public Integer baselineGet0(CacheState0 state) { reading }

我使用-wi 10 -i 10 -f 1参数来运行测试。在报告中,变量cnt对于所有基准测试都是相同的。
Benchmark                  Mode  Cnt     Score      Error  Units
Benchmark.g0               avgt   10   262,537 ?  215,406  us/op
Benchmark.g0:baselineGet0  avgt   10     2,101 ?    0,154  us/op
Benchmark.g0:baselinePut0  avgt   10  1252,231 ?  697,807  us/op

这是否意味着实验中读取的数量等于写入的数量?如果是,如何正确实现?更一般地说:在这个设置中我是否漏掉了什么?


除非你真的需要获取读/写的单独测量值,否则我更倾向于使用对称(随机化)测试,它会抛出ThreadLocalRandom支持的骰子来确定是进行读操作还是写操作。这样你可以更仔细地平衡操作混合,并且不依赖线程调度。你不会在能够容纳11个运行线程而不互相干扰的机器上运行吧?;) - Aleksey Shipilev
1个回答

1

Cnt显示的是样本数(而不是线程数)。在您的情况下,它是10,因为您正在使用-i 10运行测试。如果将所有参数设置为唯一值(例如-i 13,而@GroupThreads(10)保持不变),则更容易看出此参数不是线程数。

您还可以(临时)将输出行添加到测试中,并查看每个线程来自哪里,例如对于读取器(以及类似于带有“writer”单词的写入器):

System.out.println("reader " + Thread.currentThread().getName());

这意味着读取次数为10,写入次数也为10。你知道如何实现我在问题中描述的目标吗? - AdamSkywalker
Cnt不是读/写次数,而是样本数。由于Mode.AverageTime将尽可能多地执行操作[在时间限制内],因此您不知道读/写次数。但是再想一想,我发现在您的情况下,Cnt应该是100,所以也许您忘记提供线程数,即在类顶部使用@Threads(11)或作为命令行参数使用-t 11?如果没有,测试将使用总共1个线程运行(我认为)作为默认值。 - timbre timbre
1
你正确地获得了每个子测试的10个样本,因为在“avgt”模式下,迭代样本也会跨参与线程进行平均。因此,在每次迭代中,“put”测试从单个线程获取一个样本,“get”测试从10个线程平均获取一个样本。通过10次迭代,在两个子测试中都可以获得10个样本。这与多线程“吞吐量”测试基本相同:每次迭代的样本是所有线程的总吞吐量之和。 - Aleksey Shipilev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接