What is the performance of Groovys collection methods (regarding space(!) and time) in comparison to plain Java for-loops?
Eg for this use cases:
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()
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).
[:] creates an empty Map. The colon is there to distinguish it from [] , which creates an empty List. This groovy code: def foo = [:]
Groovy - collect()The method collect iterates through a collection, converting each element into a new value using the closure as the transformer.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With