我正在创建Scala方法以将元素添加到ArrayBuffer
中。我正在考虑2种方法:
def addToArrayBuffer(b: ArrayBuffer[Int])
def addToArrayBuffer(cb: Int => Unit)
第一种方法是获取集合并向其中添加元素的方法。第二种方法是获取回调cb
并为我要添加到集合中的每个元素调用此回调的方法。
第二种方法更加灵活,因为我可以在将元素添加到集合之前对其进行转换/过滤。
不幸的是,第二种方法比较慢(72 ops / s与57 ops / s):
Benchmark Mode Cnt Score Error Units
TestBenchmark.addToArrayBufferDirectly thrpt 9 72.808 ? 13.394 ops/s
TestBenchmark.addToArrayBufferViaCallback thrpt 9 57.786 ? 3.532 ops/s
我的问题是,为什么JVM无法优化回调并达到与直接添加到集合相同的速度?我该如何提高速度?
我在Mac上使用java
版1.8.0_162
。这是基准的来源:
package bench
import org.openjdk.jmh.annotations.{Benchmark, Fork, Measurement, Scope, State, Warmup}
import org.openjdk.jmh.infra.Blackhole
import scala.collection.mutable.ArrayBuffer
@State(Scope.Thread)
@Warmup(iterations = 5)
@Measurement(iterations = 3)
@Fork(3)
class TestBenchmark {
val size = 1000000
@Benchmark
def addToArrayBufferDirectly(blackhole: Blackhole) = {
def addToArrayBuffer(b: ArrayBuffer[Int]) = {
var i = 0
while (i < size) {
b.append(i)
i += 1
}
}
val ab = new ArrayBuffer[Int](size)
addToArrayBuffer(ab)
blackhole.consume(ab)
}
@Benchmark
def addToArrayBufferViaCallback(blackhole: Blackhole) = {
def addToArrayBuffer(cb: Int => Unit) = {
var i = 0
while (i < size) {
cb(i)
i += 1
}
}
val ab = new ArrayBuffer[Int](size)
addToArrayBuffer(i => ab.append(i))
blackhole.consume(ab)
}
}
答案 0 :(得分:1)
Scala编译器可以使用标志对其进行优化
scalacOptions ++= Seq(
"-opt-inline-from:bench.**",
"-opt:l:inline"
)
无需更改代码。有关Scala内联的更多信息:https://www.lightbend.com/blog/scala-inliner-optimizer