Scala隐式类型转换对性能有何影响

Scala隐式类型转换对性能有何影响

本文介绍了Scala隐式类型转换对性能有何影响?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Scala中,与其他可能的实现选择相比,使用隐式类型转换来增强类的功能是否会对CPU或内存产生重大影响?

In Scala, is there a significant CPU or memory impact to using implicit type conversions to augment a class's functionality vs. other possible implementation choices?

例如,考虑一个愚蠢的String操纵函数.此实现使用字符串串联:

For example, consider a silly String manipulation function. This implementation uses string concatenation:

object Funky {
  def main(args: Array[String]) {
    args foreach(arg => println("Funky " + arg))
  }
}

此实现通过使用隐式类型转换将串联隐藏在成员方法后面:

This implementation hides the concatenation behind a member method by using an implicit type conversion:

class FunkyString(str: String) {
  def funkify() = "Funky " + str
}

object ImplicitFunky {
  implicit def asFunkyString(str: String) = new FunkyString(str)

  def main(args: Array[String]) {
    args foreach(arg => println(arg.funkify()))
  }
}

两者都做同样的事情:

scala> Funky.main(Array("Cold Medina", "Town", "Drummer"))
Funky Cold Medina
Funky Town
Funky Drummer

scala> ImplicitFunky.main(Array("Cold Medina", "Town", "Drummer"))
Funky Cold Medina
Funky Town
Funky Drummer

性能上有区别吗?一些具体的注意事项:

Is there any performance difference? A few specific considerations:

Scala是否将对asFunkyString方法的隐式调用内联?

Does Scala inline the implicit calls to the asFunkyString method?

Scala确实为每个arg创建了一个新的包装器FunkyString对象,还是可以优化掉多余的对象分配?

Does Scala actually create a new wrapper FunkyString object for each arg, or can it optimize away the extra object allocations?

假设FunkyString有3种不同的方法(funkify1,funkify2和funkify3),并且foreach的主体依次调用每个方法:

Suppose FunkyString had 3 different methods (funkify1, funkify2, and funkify3), and the body of foreach called each one in succession:

println(arg.funkify1())
println(arg.funkify2())
println(arg.funkify3())

Scala会重复转换3次,还是会优化多余的转换并为每次循环迭代执行一次?

Would Scala repeat the conversion 3 times, or would it optimize away the redundant conversions and just do it once for each loop iteration?

假设我将捕获的转换明确地捕获到另一个变量中,如下所示:

Suppose instead that I explicitly capture the conversion in another variable, like this:

val fs = asFunkyString(arg)
println(fs.funkify1())
println(fs.funkify2())
println(fs.funkify3())

这会改变情况吗?

实际上,隐式转换的广泛使用是潜在的性能问题,还是通常无害?

In practical terms, is broad usage of implicit conversions a potential performance issue, or is it typically harmless?

推荐答案

我尝试使用出色的 Scala-Benchmark-Template .

编写一个仅测试隐式转换的有意义的(未经JIT优化)基准非常困难,因此我不得不增加一些开销.

It is very difficult to write a meaningful (non optimized away by the JIT) benchmark which tests just the implicit conversions, so I had to add a bit of overhead.

这是代码:

class FunkyBench extends SimpleScalaBenchmark {
  val N = 10000
  def timeDirect( reps: Int ) = repeat(reps) {
    var strs = List[String]()
    var s = "a"
    for( i <- 0 until N ) {
      s += "a"
      strs ::= "Funky " + s
    }
    strs
  }
  def timeImplicit( reps: Int ) = repeat(reps) {
    import Funky._
    var strs = List[String]()
    var s = "a"
    for( i <- 0 until N ) {
      s += "a"
      strs ::= s.funkify
    }
    strs
  }
}

结果如下:

[info] benchmark  ms linear runtime
[info]    Direct 308 =============================
[info]  Implicit 309 ==============================

我的结论:在任何不平凡的代码段中,隐式转换(对象创建)的影响都是无法衡量的.

My conclusion: in any non trivial piece of code, the impact of implicit conversions (object creation) is not measurable.

编辑:我使用了scala 2.9.0和java 1.6.0_24(在服务器模式下)

I used scala 2.9.0 and java 1.6.0_24 (in server mode)

这篇关于Scala隐式类型转换对性能有何影响?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-18 12:38