为什么Scala的foldLeft具有比使用字符串索引迭代更低的性能?

我正在比较两个atoi实现的性能.第一个是使用charat迭代输入字符串获取chars;第二个是使用foldLeft.

object Atoi {
  def withRandomAccess(str: String,baze: Int): Int = {
      def process(acc: Int,place: Int,str: String,index: Int): Int = 
        if (index >= 0) process(acc + value(str.charat(index)) * place,place * baze,str,index-1) else acc
      process(0,1,str.length - 1)
    }

  def withFoldLeft(str: String,base: Int): Int = (0/:str) (_ * base + value(_))

  def value(c: Char): Int = { /* omitted for clarity */ }

  def symbol(i: Int): Char = { /* omitted for clarity */ }
}

foldLeft版本的速度是2x到4x(完整的基准代码here).我没想到这个你知道为什么吗?在处理它之前,Scala是否将字符串转换为列表?你有什么提示如何提高foldLeft性能的字符串?

解决方法

这个问题与内联无关,它与使用foldLeft时所发生的Chars的拳击/拆箱有关.

您可以通过隐式转换为StringOps的String获取foldLeft,这不是专门的. String中的每个char必须被包装成一个java.lang.Character,以便被传递给Function2(foldLeft的参数),然后取消装箱(便宜得多)传递给函数体内的值方法,然后装箱再次进入折叠的下一个迭代.

拳击涉及创建对象和随后垃圾回收的开销.

在避免拳击方面,有一个简短而重要的一点:

>你不应该试图避免拳击,几率接近1.

(也就是说,除非你已经确定了可以归结于拳击的具体和不可接受的性能下降,否则你不应该担心.)

如果您确定需要解决的问题,请避免收集和理解(在引导下使用foreach和flatMap).如果您正在使用循环,请使用while.

相关文章

共收录Twitter的14款开源软件,第1页Twitter的Emoji表情 Tw...
Java和Scala中关于==的区别Java:==比较两个变量本身的值,即...
本篇内容主要讲解“Scala怎么使用”,感兴趣的朋友不妨来看看...
这篇文章主要介绍“Scala是一种什么语言”,在日常操作中,相...
这篇文章主要介绍“Scala Trait怎么使用”,在日常操作中,相...
这篇文章主要介绍“Scala类型检查与模式匹配怎么使用”,在日...