Friday, January 18, 2008

RE: Groovy and JRuby: Enterprise-Ready?

There is a report that is being pushed around comments on blog posts with the aim of spreading FUD. The report can be found here:

http://www.huxili.com/index.php?cat=reports&id=ID000188


It is entitled "Groovy and JRuby: Enterprise Ready?" and its conclusion is that Groovy is not due to "memory leaks". The report is complete nonsense of course, and it put together by someone who doesn't understand the different language idioms.

The report provides no code examples, further bringing to question its validity, however it states that Groovy runs out of memory when running these steps:
  1. Call shell.evaluate("x = 100")

  2. Call System.gc()

  3. Thread.sleep(1000)

  4. Record used memory

  5. Repeating (1-4)

I'm going to have a go at guessing the Groovy code they used. I can bet it goes something like this:

shell = new GroovyShell()
while(true) {
shell.evaluate("x = 100")
sleep(2000)
System.gc()
}

So what is the problem with this code? And why would it result in a memory leak? The answer is that each GroovyShell instance has an internal class loader. Groovy is a compiled language. Even little scripts like this are compiled into classes so over time the class loader just gets bigger and bigger. The solution? Here we go:

while(true) {
new GroovyShell().evaluate("x = 100")
sleep(2000)
}

So what this does is allow the GroovyShell (and its class loader) to be garbage collected by the JVM. When the class loader is garbage collected so are the classes loaded within it. JRuby of course doesn't have this problem as its interpreted.

Judging whether a language is "enterprise-ready" without knowing the language idioms and basing it on a 4 line script is to be honest quite ridiculous, so remember beware of silly "official" looking reports without verifying the facts for yourself.

15 comments:

Anonymous said...

Thanks for setting this straight. Got a little scared when I first saw that report.

Anonymous said...

Graeme,

Thanks for the clarification. But I'm still concerned. Are you saying that an incorrect usage of Groovy code within my app may possibly break the app?

Graeme Rocher said...

Absolutely, just like the incorrect usage of Java code in your app can leak too

Grails Dummy said...

In J2SE 6.0 can't we take advantage of JSR223 to have scripts cached?

Similar to the original article I have unit tests running to roughly report the performance of Groovy scripts under J2SE 5.0 and I'm looking forward to migrating to J2SE 6.0. Is my expectation of a performance improvement misplaced or I am also missing the point?

Graeme Rocher said...

Yes Groovy (and JRuby for that matter) are significantly faster on JDK 1.6

Charles Oliver Nutter said...

JRuby is not just interpreted; it can be both interpreted and compiled. Code can be run either entirely interpreted, precompiled to bytecode, or left to JIT to bytecode at runtime. This provides a balance between startup and runtime execution performance, since runtime compilation can be expensive.

Anonymous said...

There is a link where you can email them to get the report. I wonder if they send you the code they used as well.

Mark Smith said...

I'm a fan of Groovy and Grails, but your comments seem pretty much off the mark to me. Yes, it's important to understand a language's idioms. But needing to keep creating new GroovyShell objects because under the hood the runtime is generating classes that are never garbage collected? That's not understanding an idiom, that's working around a really lousy design and/or implementation.

Anonymous said...

I agree with Mark.
One of the arguments of the Groovy camp to use Groovy instead of JRuby or Scala is that it would have the easier language learning curve.
So the syntax is easier but I do need to know how the internals work to make my apps work?
Sorry but no thanks.

Graeme Rocher said...

@Mark and Ingo

You guys make valid points, maybe the GroovyShell should create a new class loader per invocation of evaluate which would fix the problem.

However, it is such a small part of the overall runtime, that to put into question Groovy's enterprise-readiness because of this behaviour is still, imo, nonsense.

The majority of use cases for Groovy nowadays are as a compiled language.

Guillaume Laforge said...

I've added some more comments on the topic of Enterprise-readiness on my blog as well: http://glaforge.free.fr/weblog/index.php?itemid=227

Guillaume Laforge said...

Forgot to put the a href tag around the link about Groovy being Enterprise-read, sorry.

Guillaume Laforge said...

@Mark, Groovy offers different mechanisms for evaluating scripts (GroovyShell, Eval, GroovyClassLoader, GroovyScriptEngine, and also BSF and JSR-223). Each of these mechanisms has its advantages and drawbacks, and depending on your needs, you may prefer to use one over the other. For instance, for this simple benchmark use case, the Eval class was the simplest one to use since its purpose is really just about evaluating expressions, instead of creating reusable classes. Eval doesn't exhibit this "keep class in memory" behavior.

When developing anything, using certain APIs, you have to know how to use them and what they are intended for. Think hammer and nails...

Regarding the "loosy idiom and/or implementation", let me remind you that Sun's JDK is full of such things all over the place (and if I dare say, it's even worse than Groovy's own APIs): you have to know some of the JDK APIs very well and how to use them properly. A good example is the JDBC support: properly handling connections, resultsets, with nested try/catch, checking for nulls, etc, frankly, that's not the nicest design I've ever seen, especially compared to Spring JdbcTemplate, or Groovy's Sql class which does all the proper handling transparently.

@Ingo, regarding the learning curve, it's about learning the syntax and idioms of the language, not necessarily about the APIs. Groovy is very easy to learn because it's 99% Java-compatible (and increasing). You also don't have to learn a hell lot of new APIs like this is the case with Ruby or Python for the JVM, you can still use Java's JDK APIs first, and if some easier-to-use APIs are more appealing, learn them, and leverage them. It's definitely the nicest learning curve of all the alternative languages on the JVM.

Anonymous said...

I find the report very odd. There is no author and the report is the only thing available on the website. http://www.huxili.com

Anonymous said...

hi there......well let me say that this is my first "workaround" with Groovy and i'm so fu++ glad to see that you guys know your business.... Well in my current job, the people with i used to work they don´t care about performance in fact they don´t know nothing about this (groovy and grails) and its very dissapointment that we're still working with a lot of old technologies and when they "survey" the market for new technologies the first comments is "How about performace??" How about an enterprise who use this language....this could be a "must read" for them....