Scala:使用回调函数降低性能的分支语句优化

时间:2016-02-23 22:41:27

标签: performance scala

在C / C ++编程中,通常使用函数指针来优化主数据路径中的分支。因此,我编写了一个测试程序,以了解使用函数式编程技术是否可以在Scala中获得类似的性能节省。用例是一个被调用了数百万次的函数,并且具有基于全局标志的分支语句。使用if()语句的代码 -

val b = true
def test() = {
  if(b) // do something
  else  // do something else
}
for(i <- 0 to 100000) test()

试图摆脱if()我做了这个 -

def onTrue() = { // do something }
def onFalse() = { // do something else }
lazy val callback: () => Unit = if(b) onTrue else onFalse
def test() = callback()
for(i <- 0 to 100000) test()

我通过为大型计数器(在for循环中)运行它们并运行它们多次并使用System.nanoTime()差异来测量这两个程序的比较来测量所花费的时间。

我的测试似乎表明回调方法实际上是SLOWER而不是在循环中使用if()。原因可能是函数调用需要将params和返回推送到堆栈并创建一个新的堆栈帧等。鉴于此发现想知道 -

  1. 是否有一种可以编码的功能方式,这将更好地在Scala循环中使用if()的性能?
  2. @inline适用于编译器。是否存在等同于避免堆栈活动的运行时? (类似于尾调用优化)
  3. 我的测试或结果可能在某种程度上不准确/错误吗?

1 个答案:

答案 0 :(得分:1)

3)以这种方式测试时,很容易弄错你的方法。如果你想要准可信的微基准测试,请使用像JMH这样的东西!

2)JVM在运行时进行内联。

1)你没有衡量某些东西是否有功能&#34;的差异。你是否正在测量使用惰性val之间的差异。如果你没有那里的懒惰,那么JVM可能会优化你的代码(取决于&#34;做某事&#34;是)。

如果你移除懒惰的val,第二个优化到我手中的相同速度。 (对于在多线程上下文中未初始化的每个访问,它都有一个额外的强制检查。)