Tuesday, April 8, 2008

Simple Java vs Groovy Perfomance Comparison

I recently read a post about doing comparisons with Groovy collections, and there was a snide comment that caught my eye:
Just write a simple helper. I guarantee that it will be 20 times faster than Groovy.
So I wrote some quick and dirty code to test exactly that. It's not scientific by any means, but my simple test showed that the Groovy version was about (edit: 7.5) times slower than the Java version.

That's still slow, but nowhere near as bad as the completely unsubstantiated claim of 20 times slower and not as bad as various other claims I've seen tossed around regarding the Java vs Groovy performance comparison.

And when you consider that Groovy is much younger than Java, that the JVM is only now starting to really get around to optimizations for languages other than Java, and that a main focus of the upcoming Groovy 1.6 release is performance improvements, that's really not bad at all.

For reference, here's the test code and the range of results for several runs. Again, it's a simple test and not scientific, but you can use it to get your own numbers. I'd love to see more people posting comparisons so that we can continue to make a factually based determination of where Groovy performance is slow.

Edit: I changed the Java version to a more compact form using Arrays.asList, increased the interations, and updated my performance numbers accordingly.

Groovy time: between 10781ms and 10688ms
Java time: between 1438ms and 1390ms
Java was roughly 7.5 times faster than Groovy (previous version was only 6 times faster)


GroovyListExamples.groovy:
-------------------------

class GroovyListExamples {

public List listSubtractionTest() {
def smallList = [1,3,5]
def bigList = [1,1,1,2,3,4,4,4,5,6,7,7,8,9]
def result = bigList - smallList
}
}

JavaListExamples.java:
---------------------

import java.util.*;

public class JavaListExamples {

public List listSubtractionTest() {
List smallList = Arrays.asList(new Object[] { 1, 3, 5});
List bigList = Arrays.asList(new Object[] { 1,1,1,2,3,4,4,4,5,6,7,7,8,9 });
return subtractList(bigList, smallList);
}

public List subtractList(List sourceList, List removeList) {
Set removeSet = new HashSet();
removeSet.addAll(removeList);

List result = new ArrayList();
for (Object item : sourceList) {
if (!removeSet.contains(item)) {
result.add(item);
}
}
return result;
}
}

ListExamplesDriver.java:
-----------------------


public class ListExamplesDriver {
public static void main(String[] args) {
GroovyListExamples groovyWay = new GroovyListExamples();
JavaListExamples javaWay = new JavaListExamples();

System.out.println("GROOVY:");
System.out.println(groovyWay.listSubtractionTest());

System.out.println("JAVA:");
System.out.println(javaWay.listSubtractionTest());

int NUMITERS = 1000000;
long start, stop;

start = System.currentTimeMillis();
for (int i = 0; i < NUMITERS; i++) {
groovyWay.listSubtractionTest();
}
stop = System.currentTimeMillis();
System.out.println("GROOVY TIME: " + (stop - start) + "ms");

start = System.currentTimeMillis();
for (int i = 0; i < NUMITERS; i++) {
javaWay.listSubtractionTest();
}
stop = System.currentTimeMillis();
System.out.println("JAVA TIME: " + (stop - start) + "ms");
}
}

4 comments:

Anonymous said...

Jim, that is really a stellar example. As I have time, I'll run both on my notebook and see what my times are, posting them here.

The time difference (6x vs 20x) doesn't surprise me, but it is still shocking to see how much java it takes to compare to a simple "-" operation in groovy.

Jim LoVerde said...

Well, to be fair, I could have written the Java code more compactly. Though at a slight performance cost. I'll update the post with a "listSubtractionTest2" method for the Java example.

Using the listSubtractionTest2 version, the Groovy fared slightly better at roughly 5 times slower than the Java version:

Groovy: between 1266ms and 1063ms
Java: between 265ms and 203ms

Jim LoVerde said...

I condensed the Java version again, and it's now actually about 7.5 times faster than the Groovy version. That's still not too bad IMO.

I also eliminated the longer version, since it would only distract from discussions about the performance.

BTW, that brings up an interesting point. Since writing Groovy code, I've actually been motivated on numerous occasions to go back and simplify/compact some Java code I've seen/written.

Valerian Mengsk said...

i concur, if and only if in vegas