关于空间/时间的 Groovy 集合性能注意事项

Posted

技术标签:

【中文标题】关于空间/时间的 Groovy 集合性能注意事项【英文标题】:Groovy collections performance considerations regarding space/time 【发布时间】:2014-07-23 11:11:59 【问题描述】:

与普通 Java for 循环相比,Groovys 收集方法(关于空间(!)和时间)的性能如何?

例如对于这个用例:

sum() 与带变量的 for 循环 each() 与带变量的 for 循环 inject() 与带变量的 for 循环 collect() 与带有临时收集的 for 循环 findAll() 与带有临时集合的 for 循环 find() 与带变量的 for 循环

那么,考虑到这些结果,是否建议在关键环境(例如 Grails-WebApp)中使用 for 循环而不是 Groovy-collection-methods?是否有关于 Groovy/Grails 性能(优化)的资源?


使用这个 GBench 测试,我得到了以下 CPU 时间结果:

                 user  system      cpu     real

forLoop       2578777      67  2578844  2629592
forEachLoop   2027941      47  2027988  2054320
groovySum     3946137      91  3946228  3958705
groovyEach    4703000       0  4703000  4703000
groovyInject  4280792     108  4280900  4352287



import groovyx.gbench.BenchmarkBuilder

def testSize = 10000
def testSet = (0..testSize) as Set


def bm = new BenchmarkBuilder().run 

'forLoop' 
    def n = 0
    for(int i = 0; i<testSize; i++) 
        n += i
    
    return n


'forEachLoop' 
    def n = 0
    for(int i in testSet) 
        n += i
    
    return n


'groovySum' 
    def n = testSet.sum()
    return n


'groovyEach' 
    def n = 0
    testSet.each  n + it 
    return n


'groovyInject' 
    def n = testSet.inject(0)  el, sum -> sum + el 
    return n


bm.prettyPrint()

【问题讨论】:

【参考方案1】:

有趣的基准。 sum() 速度较慢也就不足为奇了。下面是实现的样子:

private static Object sum(Iterable self, Object initialValue, boolean first) 
        Object result = initialValue;
        Object[] param = new Object[1];
        for (Object next : self) 
            param[0] = next;
            if (first) 
                result = param[0];
                first = false;
                continue;
            
            MetaClass metaClass = InvokerHelper.getMetaClass(result);
            result = metaClass.invokeMethod(result, "plus", param);
        
        return result;

如您所见,它必须是通用的并且使用元编程。结果是更大的时间成本。

您粘贴的基准测试结果清晰且具有自我描述性。如果您真的需要更好的性能,似乎更好的主意是使用for 循环。

【讨论】:

+1 表示“如果你真的需要更好的性能”。例如,在 IO 密集型操作或数据库驱动系统上,代码性能不应成为主要关注点。表演***者应该已经醒来了。 阿门。如果它表现“足够好”并且易于阅读和维护,那总比更快但没有人理解它要好。在你需要它之​​前,不要开始走向 0 和 1。

以上是关于关于空间/时间的 Groovy 集合性能注意事项的主要内容,如果未能解决你的问题,请参考以下文章

Groovy集合遍历 ( 使用集合的 find 方法查找集合元素 | 闭包中使用 == 作为查找匹配条件 | 闭包中使用 is 作为查找匹配条件 | 闭包使用 true 作为条件 | 代码示例 )

Groovy集合遍历 ( 使用集合的 find 方法查找集合元素 | 闭包中使用 == 作为查找匹配条件 | 闭包中使用 is 作为查找匹配条件 | 闭包使用 true 作为条件 | 代码示例 )(代

使用 Groovy 检查对象是不是在集合中

Groovy使用List集合

如何将Groovy String集合转换为Java String Array?

Groovy03_集合