Thursday, August 28, 2008

Hey Guillaume Laforge, Thai Geeks are going to interview you

After Groovy has been got the big attention in Thai community this moment, I've been co-operating with Isriya of Blognone.com (a leading technology news site in Thailand) to arrange an interview for Guillaume Laforge. This interview will be a community-based. All question will come from news readers, which of course are Thai geeks. After collecting questions there, I'll forward them to Guillaume via email.

This will be the first time for them to get in touch with him.

See the post (if you can read Thai): http://www.blognone.com/node/8770

Friday, August 15, 2008

Do anything at BarCamp Bangkok 2

To help promote BarCamp Bangkok 2, here's my screencast:

http://screencast.com/t/JRZprfG6

Enjoy !

A Java-near-speed Groovy

Almost 2 months that I have not posted here. I'm still in the final phase of Google Summer of Code. The world is going to be wonderful when you have got a really good result from your hard work, is that right ?

I'm currently be able to make Groovy speed step closer to Java. It's a high aim, and it's clear to be possible with JVMIT now. I was working on optimising callsites, but could not find a way to make it faster than Alex T.'s implementation because he did really good job of implementing it. So I went back to look at my old GJIT code. What I found is that something had been fooling my eyes for almost a year. There is a way to avoid JVM 6 specific code to implement an agent for JVM 5. Then I re-read AspectJ source again, and found something useful. I has started to re-write a GJIT agent for JVM 5 from then.

My prototype of the second generation of GJIT was done with Soot framework, where I really learned a lot of useful optimisation tricks (e.g., SourceValue). Later, I found that Soot is not suite for implementing JIT, because of 1. it's somewhat big structure 2. it's class loading problem. I then have had to implement a whole thing using ASM. It really was a nightmare because there is no Jimple to help your analysis. I re-wrote at least 3-4 version of ASM optimisers, and finally got the current one, which has a good enough structure to patch.

Now my goal is to beat all shootout benchmarks. Here's the result from partial sums benchmark compared with Java on my machine.


$ export JAVA_OPTS="-server"
$ time `java -cp bin alioth.PartialSumsJ 5000000`
real 0m10.246s
user 0m0.030s
sys 0m0.015s

$ time `groovy.bat test/partial_sums.groovy 5000000`
real 0m27.110s
user 0m0.030s
sys 0m0.016s

$ time `groovy.bat test/alioth/PartialSums.groovy 5000000`
real 0m28.409s
user 0m0.030s
sys 0m0.015s

$ export JAVA_OPTS="-server
-javaagent:C:\\groovy-ck1\\healthy\\target\\install\\lib\\gjit-0.1.jar"
$ time `groovy.bat test/alioth/PartialSums.groovy 5000000`
real 0m13.434s
user 0m0.030s
sys 0m0.030s



It's 200% faster than current Groovy, and ~20-30% slower than Java. There's still room to go. I hope to take some more steps closer to Java's speed.

Saturday, June 21, 2008

Expression-Wide Optimisation (Primitive Callsite #2)

This is a technique I proposed for optimizing Groovy primitive expressions.

Let's say, we have:
public double a(int i, int j) {
return 1 / ((i+j)*(i+j+1)/2.0D +i+1);
}
This expression consists of 7 callsites. If we can make sure that the following 3 conditions
1. All variables are primitive.
2. The metaclass of each callsite is default
3. The meta method of each callsite is default
are true, the we can replace the entire expression with primitive and native Java bytecodes. Thus, we can by-pass any overhead here.

When some meta-method has been replaced, then the above condition is invalid. The original code will be performed instead of the fast one.

This technique is reasonable to implement because:
1. Callsite makes this checking cheap. We can define "isDefault" flag for a "default" callsite.
2. Instead of checking the default flag one-by-one, checking these flags for a whole expression makes this even cheaper. This also results in easier code generation.

However, we have to generate code twice, say fast and slow paths, for each expression-to-be-optimised.


final boolean exprCallSet = $getExprCallSet(0);
if(exprCallSet) {
return 1 / ((i+j)*(i+j+1)/2.0D +i+1);
} else {
$reevaluateExprCallSet.get()[0] = true;
return DefaultTypeTransformation
.doubleUnbox(ScriptBytecodeAdapter.castToType(
acallsite[0].call($const$0, acallsite[1].call(
acallsite[2].call(acallsite[3].call(
acallsite[4].call(acallsite[5].callOII(i, j),
acallsite[6].call(acallsite[7].callOII(i,j),$const$0)),
$const$1),
DefaultTypeTransformation.box(i)),
$const$0)),
$get$$class$java$lang$Double()));
}


The above snippet is a mock code I'm working on. The next step is to generalise this and modify the Groovy class generator. With this technique, we can unleash all power of Java primitives which will be > 800% faster than the normal callsite caching in 1.6-beta1.