如何解决Scala 2运行时反射动态编译多函数的性能衰减问题?
Scala运行时反射动态生成函数的性能衰减问题
我通过Scala 2的运行时反射动态编译生成Scala函数,实际场景更复杂,但以下代码可复现核心问题:
import scala.reflect.runtime.universe._ import scala.tools.reflect.ToolBox object Generator { val toolbox = reflect.runtime.currentMirror.mkToolBox() def generate(value: Long): Long => Long = toolbox.eval(q"(x: Long) => x + $value").asInstanceOf[Long => Long] }
我发现动态编译的函数数量越多,执行性能会出现显著衰减。以下是用于验证的JMH基准测试代码:
import java.util.concurrent.TimeUnit import scala.util.Random import org.openjdk.jmh.annotations._ @State(Scope.Benchmark) @BenchmarkMode(Array(Mode.AverageTime)) @OutputTimeUnit(TimeUnit.NANOSECONDS) class BenchmarkGenerator { @Param(Array("1", "10", "100", "1000", "10000")) var nFunctions: String = _ var evalF: List[Long => Long] = _ @Setup def setup() = evalF = (0 until nFunctions.toInt).map(_ => Generator.generate(Random.nextLong(100000000L))).toList @Benchmark def evaluate() = evalF.foreach(_(1L)) }
在我的机器上运行后得到如下结果:
Benchmark (nFunctions) Mode Cnt Score Error Units BenchmarkGenerator.evaluate 1 avgt 5 1.320 ± 0.020 ns/op BenchmarkGenerator.evaluate 10 avgt 5 38.683 ± 0.249 ns/op BenchmarkGenerator.evaluate 100 avgt 5 410.243 ± 4.137 ns/op BenchmarkGenerator.evaluate 1000 avgt 5 14797.026 ± 1003.635 ns/op BenchmarkGenerator.evaluate 10000 avgt 5 869938.386 ± 307011.008 ns/op
我原本预期执行时间会接近线性增长,但实际衰减幅度远超出线性范围。另外我发现,即便编译大量函数,只要重复执行单个函数,性能就能保持稳定。我怀疑是编译后的函数被JVM卸载,导致再次执行时需要重新编译,进而大幅变慢。
请问有没有方法排查这个问题?是否可以通过JVM调优或其他手段解决该性能衰减问题?
内容的提问来源于stack exchange,提问作者jcazevedo
相关产品推荐
相关产品推荐

