首页 > 解决方案 > 确认 for 循环和流性能的 JMH 基准测试的有效性

问题描述

我决定要对简单的流操作进行一些测量,将它们与相应的流前迭代结构进行比较。

我有一个一定长度的 ArrayList,这样所有的列表元素都是三个字符串。

以下是相关的基准测试方法:

@Benchmark
public long shortLengthConstantSizeFor() {
    long count   = 0;
    for (String val : shortLengthListConstantSize) {
        if (val.length() == 3) { ++ count; }
    }
    return count;
}

@Benchmark
public long shortLengthConstantSizeForEach() {
    IntHolder   intHolder   = new IntHolder();
    shortLengthListConstantSize.forEach(s -> { if (s.length() == 3) ++ intHolder.value; } );
    return intHolder.value;
}

@Benchmark
public long shortLengthConstantSizeLambda() {
    return shortLengthListConstantSize.stream().filter(s -> s.length() == 3).count();
}

@Benchmark
public long shortLengthConstantSizeLambdaParallel() {
    return shortLengthListConstantSize.stream().parallel().filter(s -> s.length() == 3).count();
}

我想与社区确认的是这些是否“功能等效”,并且真的会衡量它们看起来正在衡量的东西。我不在这里提供测量值,因为那会分散注意力。

请注意,“shortLength”是指“短列表”。我也有这些方法的几个块,具有不同长度的列表,最多一个具有 300k 个元素。

标签: javajava-streamjmh

解决方案


如果通过“功能等效性”您的意思是每种方法执行相同的功能或测量,包括副作用 - 它似乎是这样。

有人可能会争辩说,在第二种方法中,您应该使用LongHolder而不是IntHolder匹配函数的 codomain。但是,如果您的“价值”实际上是long此类中的一个 - 那么它就是一个通行证。

值得一提的count()是,这只是一个简写,map(x -> 1L).sum()但对于这个基准没有任何改变。


推荐阅读