Groovy:闭包明显慢于方法?

Mic*_*ier 5 performance groovy closures

在使用不同的排序算法时,我很惊讶Groovy关闭的表现非常糟糕.到目前为止我找不到一个好的答案,所以现在试试我的运气;)为什么Groovy闭包比传统方法慢得多?

这是一个显示性能差异的简单示例.它创建两个带有随机数的列表,并按相反的顺序对它们进行排序,测量排序时间.在我的机器和10k元素上,使用闭包需要270ms,使用Comparator实现只需50ms.

根据随机数的分布,时间稍有不同.我也尝试了Groovy 1.7.4和1.8.0,后者的性能稍好一些.但整体情况保持不变:关闭表现不佳.

我该怎么做才能提高闭合性能?当然,除了不使用闭包之外;)我是否遗漏了某些东西,或者如果性能很重要,是否应该在groovy中使用闭包?

def numberCount = 10000
def random = new Random()
def unorderedList1 = (1..numberCount).collect{random.nextInt()}
def unorderedList2 = (1..numberCount).collect{random.nextInt()}
def timeit = {String message, Closure cl->
    def startTime = System.currentTimeMillis()
    cl()
    def deltaTime = System.currentTimeMillis() - startTime
    println "$message: \ttime: $deltaTime"
}

timeit("compare using closure") {
    def comparator= [ compare: { a,b -> return b <=> a }] as Comparator
    unorderedList1.sort(comparator)
}

timeit("compare using method") {
    Comparator comparator = new MyComparator()
    unorderedList2.sort(comparator)
}

class MyComparator implements Comparator {
    int compare(a, b) {return b <=> a}
}
Run Code Online (Sandbox Code Playgroud)

vip*_*phe 5

只是在 Ubuntu 上使用 OpenJDK 1.6 (O6) 和 JDK 1.7 (J7) 更新了 Groovy 2.0.5。

我还添加了两种可能的实现:

  • 仅提供一个闭包作为 Comparator 的实现:
  • 用@CompileStatic注释的方法:

    def numberCount = 10000
    def random = new Random()
    def unorderedList1 = (1..numberCount).collect{random.nextInt()}
    def unorderedList2 = (1..numberCount).collect{random.nextInt()}
    def unorderedList3 = (1..numberCount).collect{random.nextInt()}
    def unorderedList4 = (1..numberCount).collect{random.nextInt()}
    def timeit = {String message, Closure cl->
        def startTime = System.currentTimeMillis()
        cl()
        def deltaTime = System.currentTimeMillis() - startTime
        println "$message: \ttime: $deltaTime"
    }
    
    timeit("compare using map of closures") {
        def comparator= [ compare: { a,b -> return b <=> a }] as Comparator
        unorderedList1.sort(comparator)
    }
    
    timeit("compare using one closure") {
        def comparator= { a, b -> return b <=> a } as Comparator
        unorderedList2.sort(comparator)
    }
    
    timeit("compare using method") {
        Comparator comparator = new MyComparator()
        unorderedList3.sort(comparator)
    }
    
    timeit("compare using method with @CompileStatic") {
        Comparator comparator = new MyComparator2()
        unorderedList4.sort(comparator)
    }
    
    class MyComparator implements Comparator {
        int compare(a, b) {return b <=> a}
    }
    
    class MyComparator2 implements Comparator<Integer> {
        @groovy.transform.CompileStatic
        int compare(Integer a, Integer b) {return b <=> a}
    }
    
    Run Code Online (Sandbox Code Playgroud)
Groovy 2.0.5 groovy groovyc
                            O6 O6 J7
关闭地图 258 499 146
一封闭 64 205 48
方法 29 37 32
@CompileStatic方法 28 26 22

请注意,我没有安装使用 JDK7 编译的 Groovy 命令行(我提取的命令行会自动安装其自己的 OpenJDK6),因此缺少相应的列。


Dón*_*nal 4

我可以做些什么来提高关闭性能?

等待。JDK7 将添加一条名为invokeDynamic的新指令,有望从根本上提高 JVM 上动态语言的性能。

  • 作为关于“def comparator= [compare: { a,b -&gt; return b &lt;=&gt; a }] as Comparator”如何工作的快速注释,它返回一个扩展[java.lang.reflect. Proxy](http://download.oracle.com/javase/6/docs/api/java/lang/reflect/Proxy.html),并与“Comparator”具有相同的签名。这意味着任何对“comparator”对象的调用都将是间接的,因此需要更长的时间。为了对列表进行排序,这个“Proxy”对象被调用大约“120000”次,因此时间上存在差异。 (3认同)