代码之家  ›  专栏  ›  技术社区  ›  rogerdpack

为什么clojure在alioth基准测试中的表现比scala差

  •  11
  • rogerdpack  · 技术社区  · 14 年前

    http://shootout.alioth.debian.org/u32q/compare.php?lang=clojure Clojure比java-server慢得多,而scala则慢得多。

    给什么?

    裁判: On Performance and Java Interoperability: Clojure vs. Scala

    6 回复  |  直到 7 年前
        1
  •  11
  •   mikera    13 年前

    您可以用任何语言编写快速或慢速代码:-)

    基于对一些Clojure代码的快速检查,我认为性能差异的主要原因是Clojure基准代码还没有完全优化以使用可用的最快语言功能。

    例如,Clojure中的以下特性都非常酷,对于开发方便非常有用,但是会产生一些运行时性能开销:

    • 惰性序列和列表
    • 使用反射的动态Java互操作性
    • 运行时函数组合/一级函数
    • 多方法/动态调度
    • 使用eval或在REPL上动态编译
    • 大整数算法

    如果你想要绝对的最大性能(以额外的复杂性为代价),你会想要重写代码来避免这些,并使用类似的东西:

    • 静态式暗示(避免反射)
    • 瞬变
    • 宏(用于编译时代码操作)
    • 协议
    • Java原语和数组
    • 循环/重复迭代

    通过明智地使用上面的代码,我发现在Clojure 1.2+中,通常可以非常接近Java性能,例如,考虑使用以下代码进行一百万次添加:

    未经选择的Clojure 使用惰性序列和大整数算法。它很好,很实用,但速度不是特别快:

    (reduce 
      (fn [acc val] (unchecked-int (unchecked-add (int acc) (int val)))) 
      (range 0 1000000))
    
    => "Elapsed time: 65.201243 msecs"
    

    优化Clojure 使用原始算术和循环/重复:

    (loop [acc (int 0) i (int 0)] 
      (if (>= i (int 1000000)) 
        acc 
        (recur (unchecked-add acc i) (unchecked-inc i)) ))
    
    => "Elapsed time: 0.691474 msecs"
    

    爪哇 代码,一个非常标准的迭代循环:

    public static int addMillion() {
        int result=0;
        for (int i=0; i<1000000; i++) {
            result+=i;
        }
        return result;
    }
    
    => "Elapsed time: 0.692081 msecs"
    

    p、 我在Clojure代码中使用了uncheckedd而不是+来匹配Java的整数溢出行为。

        2
  •  4
  •   Alex Cruise    14 年前

    Clojure是一种动态语言,它必须执行大量额外的运行时检查。

    编辑,现在不那么轻率了:不看基准的实际Clojure实现,性能差异也可能归因于习惯性的Clojure代码避开了可变状态,而且,在其他条件相同的情况下,使用可变状态的算法通常比不使用可变状态的算法好。

    给定的程序员是否能够编写使用可变状态的代码 正确地 这是一个不同的问题,当然,纯函数代码的声明性本质意味着至少在理论上,许多优化成为可能。

        3
  •  3
  •   Alex Taggart    14 年前

    部分原因是测试本身,即您必须编写代码(无论是什么语言)来执行 准确的 与Java版本相同的实现步骤。哦,你有一个不同的,可能更快的方法 用你的语言?太糟糕了。

    当测试的基础是循环和数组bashing以及需要多个浮动代码块的通用命令式样式时,您将得到无意义的数字。

        4
  •  2
  •   David Plumpton    14 年前

    写一些更快的版本看起来可能很有趣。。。

        5
  •  1
  •   dnolen    14 年前

    许多基准测试都比较慢,因为直到最近,Clojure还需要更多的工作和专家知识才能获得良好的性能。这些基准大多以1.2为目标。

    Clojure 1.3有很多改进,使编写性能代码变得简单多了。尽管社区中没有那么多人熟悉如何提高Clojure代码的性能,但随着人们提交更好的版本,这将是一个渐进的过程。

        6
  •  -1
  •   Diego Sevilla    14 年前

    Scala特性通常是一点一点地引入的,并且在大多数情况下会指定相应的Java代码。这将Scala转换为Java的一种进化,它考虑了新特性和性能之间的平衡。

    另一方面,Clojure在设计时考虑到了一种非常不同的编程方法,并且具有与Java互操作的特性。然而,两种语言之间的阻抗不匹配(而且JVM是为Java准备的)可能会使Clojure稍微慢一点。对于某些问题,Clojure可能更快(例如使用不可变集合),但对于大多数应用程序来说可能不是。