Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Groovy collections performance considerations regarding space/time

What is the performance of Groovys collection methods (regarding space(!) and time) in comparison to plain Java for-loops?

Eg for this use cases:

  • sum() vs. for-loop with variable
  • each() vs. for-loop with variable
  • inject() vs. for-loop with variable
  • collect() vs. for-loop with temporary collection
  • findAll() vs. for-loop with temporary collection
  • find() vs. for-loop with variable

So, considering those results, is it advisable to use for-loops over Groovy-collection-methods in critical environments (eg. Grails-WebApp)? Are there resources regarding Groovy/Grails performance (optimization)?


Using this GBench test I got the following results for CPU-time:

                 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()
like image 507
matcauthon Avatar asked Jun 03 '14 07:06

matcauthon


People also ask

Why is groovy slow?

Yet, Groovy has to do it, in order to stay inter-operable with Java. All that makes Groovy pretty slow. In fact much slower and, what is more painful, more memory consuming than most of the dynamic languages out there (Python for instance).

What does [:] mean in groovy?

[:] creates an empty Map. The colon is there to distinguish it from [] , which creates an empty List. This groovy code: def foo = [:]

What is collections in Groovy?

Groovy - collect()The method collect iterates through a collection, converting each element into a new value using the closure as the transformer.


1 Answers

Interesting benchmark. No surprise that sum() is slower. Here's how implementation looks like:

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;
}

As You can see it must be generic and uses meta programming. The result is bigger time cost.

The results of the benchmark You pasted are clear and pretty self descriptive. If You really need better performance it seems that better idea is to use for loops.

like image 127
Opal Avatar answered Nov 09 '22 18:11

Opal