【问题标题】:Scala Performance: imperative vs functional styleScala 性能:命令式与函数式风格
【发布时间】:2011-03-20 16:36:07
【问题描述】:

我是 Scala 新手,正在阅读 Scala By Example。在第 2 章中,作者有 2 个不同版本的 Quicksort。

一种是命令式风格:

def sort(xs: Array[Int]) {
    def swap(i: Int, j: Int) {
        val t = xs(i); xs(i) = xs(j); xs(j) = t
    }
    def sort1(l: Int, r: Int) {
        val pivot = xs((l + r) / 2)
        var i = l; var j = r
        while (i <= j) {
            while (xs(i) < pivot) i += 1
            while (xs(j) > pivot) j -= 1
            if (i <= j) {
                swap(i, j)
                i += 1
                j -= 1
            }
        }
        if (l < j) sort1(l, j)
        if (j < r) sort1(i, r)
    }
    sort1(0, xs.length - 1)
}

一种是功能风格:

def sort(xs: Array[Int]): Array[Int] = {
  if (xs.length <= 1) xs
  else {
    val pivot = xs(xs.length / 2)
    Array.concat(
      sort(xs filter (pivot >)),
           xs filter (pivot ==),
      sort(xs filter (pivot <)))
  }
}

函数式风格相对于命令式风格的明显优势是简洁。但是性能呢?由于它使用递归,我们是否像在其他命令式语言(如 C)中那样为性能损失付出代价?或者,Scala 是一种混合语言,“Scala 方式”(函数式)是首选,因此效率更高。

注意:作者确实提到了函数式样式确实使用了更多的内存。

【问题讨论】:

  • “简洁”与“可读”不同。证据:the J programming language
  • 我想我现在明白了,Scala By Example 的作者试图展示另一种更简洁的解决问题的方法。总而言之:您在代码的所有部分中尽可能简洁地编程,这样您就可以获得最大的简洁性和生产力。然后运行您的应用程序,如果它太慢,请对其进行分析并优化瓶颈部分。

标签: scala performance functional-programming imperative


【解决方案1】:

这取决于。如果您查看 Scala 源代码,通常会在“幕后”使用命令式样式以提高性能 - 但在许多情况下,正是这些调整允许编写高性能功能 em> 代码。所以通常你可以想出一个足够快的功能解决方案,但你必须小心并知道你在做什么(尤其是关于你的数据结构)。例如。第二个示例中的数组 concat 不太好,但可能还不错 - 但是在这里使用列表并将它们与 ::: 连接起来会有点过头了。

但是,如果您实际上不衡量性能,那也不过是有根据的猜测。在复杂的项目中,很难预测性能,尤其是当对象创建和方法调用等事情越来越多地被编译器和 JVM 优化时。

我建议从功能样式开始。如果速度太慢,请对其进行分析。通常有更好的功能解决方案。如果没有,您可以使用命令式风格(或两者兼而有之)作为最后的手段。

【讨论】:

  • 但这有点违背了目的,对吧?我的意思是,Scala 被誉为第一个连接函数式编程和对象编程的语言。但是,如果你不能确定函数式编程是否高效,那么关心性能的人最终会以“Java”方式编写 Scala 吗?
  • 看例子。哪一个看起来更容易理解?函数式风格实际上告诉您算法的作用:“选择一个枢轴元素,对较小的元素进行排序,对较大的元素进行排序并将所有内容放在一起”。与主要关注循环变量和数组索引的命令式示例相比,这是一个巨大的优势。因此,如果函数式风格运作良好,我们通常是黄金,但我们仍然有命令式风格作为后备解决方案。但是不要设置面向对象 == 命令。类和对象可以在函数式上下文中很好地工作。
  • 在任何大型项目中,您都会发现实际上需要非常高效的代码很少。在这些情况下,确实经常需要回退到命令式构造。 Scala 支持这一点。剩下的时间,你最好以这样一种方式编码,即你的设计在你的代码中尽可能清晰。这可能是功能性的、过程性的、面向对象的或它们的某种组合。 Scala 支持所有这些。
  • @ShaChris23 你期待什么?当然,你不能确定函数式编程总是高效的,就像以命令式或 OO 风格编写程序并不总是高效一样。函数式编程并不是能自动提高程序效率的灵丹妙药,这与 Scala 本身没有任何关系。在任何编程风格中,您都不能免费获得效率,您仍然需要自己考虑。
  • 感谢@Landei、@Dave 和@Jesper 提供的所有体贴的 cmets。
猜你喜欢
  • 2013-10-11
  • 2016-03-20
  • 1970-01-01
  • 2021-08-23
  • 1970-01-01
  • 2012-05-12
  • 2011-05-09
  • 2014-03-20
  • 1970-01-01
相关资源
最近更新 更多