为什么 JVM 不优化简单的回调(在 Scala 中)?
Why JVM doesn't optimize simple callback (in Scala)?
我正在创建 Scala 方法以将元素添加到 ArrayBuffer
。我正在考虑两种方法:
def addToArrayBuffer(b: ArrayBuffer[Int])
def addToArrayBuffer(cb: Int => Unit)
第一种方法是获取集合并将元素添加到其中的方法。第二种方法是获取回调 cb
并为我要添加到集合中的每个元素调用此回调的方法。
第二种方法更灵活,因为我可以 transform/filter 个元素,然后再将它们添加到集合中。
不幸的是,第二种方法较慢(72 ops/s vs 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)
}
}
Scala 编译器可以使用 flags 对其进行优化
scalacOptions ++= Seq(
"-opt-inline-from:bench.**",
"-opt:l:inline"
)
无需更改代码。有关 Scala 内联的更多信息:https://www.lightbend.com/blog/scala-inliner-optimizer
我正在创建 Scala 方法以将元素添加到 ArrayBuffer
。我正在考虑两种方法:
def addToArrayBuffer(b: ArrayBuffer[Int])
def addToArrayBuffer(cb: Int => Unit)
第一种方法是获取集合并将元素添加到其中的方法。第二种方法是获取回调 cb
并为我要添加到集合中的每个元素调用此回调的方法。
第二种方法更灵活,因为我可以 transform/filter 个元素,然后再将它们添加到集合中。
不幸的是,第二种方法较慢(72 ops/s vs 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)
}
}
Scala 编译器可以使用 flags 对其进行优化
scalacOptions ++= Seq(
"-opt-inline-from:bench.**",
"-opt:l:inline"
)
无需更改代码。有关 Scala 内联的更多信息:https://www.lightbend.com/blog/scala-inliner-optimizer