A blog about software development and other software related matters

Blog Archive

Thursday, December 13, 2007

Compilled vs non compilled Groovy Spring beans

Spring offers great flexibility when working with dynamic languages, it enables the wiring of Groovy beans in your application with minimal effort (see), one of the coolest things about it is that it enables also the re-deployment of Groovy code with no more then a simple file override (see).

All this is fine and dandy except that it introduces quite an overhead on Spring context startup time and runtime usage, developers that use it may get the wrong impression that Groovy is Sloowww (partly true).
The fact is (as ill demonstrate next) that Spring's magic takes its toll and that there is a simple alternative to this mechanism which is to use the compiled code and not the source code in our bean definitions.

Take for example the following configurations:


Compiled:
⟨bean id="multiThreadedConversion" class="com.conversion.MultiThreadedConversion" scope="singleton"⟩
⟨property name="mapper" ref="mapper"/⟩
⟨bean⟩

⟨bean id="mapper" class="com.conversion.utils.ExtensionToAppMapper" scope="singleton"/⟩

⟨bean id="scavenger" class="com.conversion.utils.ConversionDataScavenger" scope="singleton"/⟩


Not compiled:
⟨lang:groovy id="multiThreadedConversion" script-source="classpath:com/conversion/MultiThreadedConversionNotCompiled.groovy" scope="singleton"⟩
⟨lang:property name="mapper" ref="mapper"/⟩
⟨/lang:groovy⟩

⟨lang:groovy id="scavenger" script-source="classpath:com/conversion/utils/ConversionDataScavenger.groovy" scope="singleton"/⟩

⟨lang:groovy id="mapper" script-source="classpath:com/conversion/utils/ExtensionToAppMapper.groovy" scope="singleton"/⟩

And two simple startup time benchmarks:


public void compiled() {
Date before = new Date();
ApplicationContext compiled = new ClassPathXmlApplicationContext("application.xml");
System.out.println(new Date().getTime() - before.getTime());
}

public void notCompiled() {
Date before = new Date();
ApplicationContext notCompiled = new lassPathXmlApplicationContext("not_compiled_application.xml");
System.out.println(new Date().getTime() - before.getTime());
}

Running them both resulted with the compiled version taking 0.203s to run and the the non compiled took 1.015s which is ~five times slower!

Should we conclude that the compiled version is always preferable?
Well it depends since it has its drawbacks:
  • We lose the easy deployment procedure when using the byte code.

  • G/Setter must be introduced in order to aid spring in identifying properties within classes (a serious draw back since in groovy we may use only the def keyword).
    It seems that iv got this wrong (just match the Spring id with the Groovy property name and your set).

This leads to the answer:
Use the source when easy redeployment (business logic is one good example) is required, use compiled when performance is critical.

Keep on Grooving ..

No comments: