Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 为什么是Scala';s foldLeft的性能低于使用字符串索引进行迭代?_Performance_Scala_Functional Programming - Fatal编程技术网

Performance 为什么是Scala';s foldLeft的性能低于使用字符串索引进行迭代?

Performance 为什么是Scala';s foldLeft的性能低于使用字符串索引进行迭代?,performance,scala,functional-programming,Performance,Scala,Functional Programming,我正在比较两个atoi实现的性能。第一种方法是使用charAt对输入字符串进行迭代以获取字符;第二种是使用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 + valu

我正在比较两个atoi实现的性能。第一种方法是使用
charAt
对输入字符串进行迭代以获取字符;第二种是使用
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, 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
版本的速度要慢2到4倍(完整的基准代码是)。我没想到会这样。你知道为什么吗?Scala是否在处理字符串之前将其转换为
列表
?关于如何提高字符串的
foldLeft
性能,您有什么提示吗?

问题与内联无关,而是与使用
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, 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 */ }
}
通过隐式转换为
StringOps
,您可以在
String
上获得
foldLeft
,这不是专门的。字符串中的每个
char
必须装箱到
java.lang.Character
中才能传递到
Function2
(foldLeft
的参数),然后取消装箱(便宜得多)传递到函数体中的
value
方法,然后再次装箱,送入下一次折叠

装箱涉及到创建对象以及随后对其进行垃圾收集的开销


关于避免拳击,有以下一个简单而重要的要点:

  • 你不应该试图避免拳击,概率几乎为1
(也就是说,除非您已经确定了可归因于拳击的特定且不可接受的性能下降,否则您不必担心。)


如果您确定存在需要解决的问题,请避免使用集合和
for
-理解(在引擎盖下使用
foreach
flatMap
)。如果正在使用循环,请在使用时使用

+1,这是使用Scala时的性能注意事项之一。(句法)糖真的让人发胖:)我想知道专业化能在多大程度上解决这类问题。@Kipton-专业化只有在藏书库专业化的情况下才能解决这个问题,这是一个非常重要的问题。我如何修改我的代码以避免不必要的装箱/拆箱?@Chaker-我想说的第一点是,你不应该这样做,概率几乎为1。也就是说,除非您已经确定了可归因于拳击的特定且不可接受的性能下降,否则您不应该担心它。如果您确定存在需要解决的问题,请避免收集和理解(在引擎盖下使用
foreach
flatMap
)。如果您使用的是循环,请使用
while