About Me

My photo
Author of Groovy modules: GBench, GProf, Co-author of a Java book パーフェクトJava, Game Developer at GREE

Saturday, December 22, 2012

Multiple Dispatch in Modern JVM Languages

What is dispatch?

"dispatch" in the context of object-oriented languages means that calling one of subroutines that have the same names by checking the parameters dynamically. There are multiple and single for dispatch. I'll write about dispatch and its support in Java and other modern JVM languages in this post.

Java

Java is "single dispatch". I'll describe it with an example of handling touch events. Let me assume that there are classes that express touch events and they have parent class named TouchEvent, also, there is TouchEventHandler that handles touch events (the y might have a virtual upper layer in an actual API).

class TouchEvent {}
 
class TouchStartEvent extends TouchEvent {}
class TouchMoveEvent extends TouchEvent {}
class TouchEndEvent extends TouchEvent {}
class TouchCancelEvent extends TouchEvent {}
 
class TouchEventHandler {
    void handle(TouchEvent e) {}
} 

Let me assume that you want to create a handler that changes behaviour depending on if the the parameter is TouchEvent or TouchStartEvent. I guess that you will write code like this if you expect subtype polymorphism.

class MyTouchEventHandler extends TouchEventHandler {
    public void handle(TouchEvent e) {
        System.out.println("... ?:(");
    }
    public void handle(TouchStartEvent e) {
        System.out.println("touch started :)");
    }
}

But the code doesn't work well.

TouchEventHandler h = new MyTouchEventHandler();
h.handle(new TouchStartEvent()); // prints "... ?:("

Java refers MyTouchEventHandler but it calls handle(TouchEvent) but not handle(TouchStartEvent). In more technical terms, Java resolves the type of the receiver dynamically but resolves the other parameters statically when sending the message. This is called "single dispatch". I'll modify the code to enhance the gap between expect for the code and compiler's opinion.

class MyTouchEventHandler extends TouchEventHandler {
    @Override public void handle(TouchEvent e) {
        System.out.println("... :(");
    }
    @Override public void handle(TouchStartEvent e) {
        System.out.println("It's my turn! :)");
    }
}

Then compiler will say

src/Overloading.java:19: error: method does not override or implement a method from a supertype
    @Override public void handle(TouchStartEvent e) {
    ^

There is a way to simulate "multiple dispatch" in Java code (without tricks in compilation phase) and I'll describe it in the following section about Xtend.

Xtend

Xtend is a relatively new JVM language that has appeared in the last year ("relatively" means that a new JVM language has appeared in this year too). Xtend is "single dispatch" as Java, but it also supports "multiple dispatch" by "dispatch" keyword.

class MyTouchEventHandler extends TouchEventHandler {
    def dispatch void handle(TouchEvent e) {
        println("... :(")
    }
    def dispatch void handle(TouchStartEvent e) {
        println("touch started :)")
    }
}

val TouchEventHandler h = new MyTouchEventHandler()
h.handle(new TouchStartEvent()) // prints "touch started :)"

It's easy to grasp what Xtend does because Xtend generates Java files instead of class files. Xtends puts a proxy method that delegates to methods have "dispatch" keyword. This is the way to simulate "multiple dispatch" in Java that I mentioned before.

public class MyTouchEventHandler extends TouchEventHandler {
  protected void _handle(final TouchEvent e) {
    InputOutput.<String>println("... :(");
  }
 
  protected void _handle(final TouchStartEvent e) {
    InputOutput.<String>println("touch started :)");
  }
 
  public void handle(final TouchEvent e) {
    if (e instanceof TouchStartEvent) {
      _handle((TouchStartEvent)e);
      return;
    } else if (e != null) {
      _handle(e);
      return;
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.<Object>asList(e).toString());
    }
  }
}

I think that using one underscore for prefix isn't nice because programmers need to worry about naming collision but let's leave it aside for now. My interest is why Xtend is "single dispatch" by default. I asked the question to Sven Efftinge who is one of the authors of Xtend and he answered "because changing method resolution would impose many interop issues with existing Jave libs". I guess it's unhappy that spoiling writability of new lauguage for taking care about bad old Java code depend on "single dispatch" but it might be because that I have never had an awful experience. Anyway, Xtend supports "multiple dispatch".

Groovy

Groovy is "multiple dispatch". The example for Java works perfectly in Groovy as expected. It is so intuitive.

TouchEventHandler h = new MyTouchEventHandler();
h.handle(new TouchStartEvent()); // prints "touch started :)"

The type of the parameters are detected dynamically and handle(TouchStartEvent) is called. I'll explain more details. Groovy replaces the method call with a CallSite object that has the caller class, the index for the call, and the method name. It is like this by expressing in code.

TouchEventHandler h = new MyTouchEventHandler();
CallSite handleN = // create a call site for the "n:handle"
handleN.call(h, new TouchStartEvent());

CallSite searches the target method gradually by listing up the meta data of "handle" methods of MyTouchEventHandler and checking the number and the type of the parameters. Of course this dynamic resolution comes at a cost but CallSite caches the method and will call the method immediately at the second time. Recent Groovy has @StaticCompile that is an annotation for turning off dynamic capabilities. Where use the annotation is compiled to binary that doesn't use CallSites and calls methods statically. In that case "multiple dispatch" doesn't work.

Others

I checked a bit about "multiple dispatch" support of other JVM languages. It is seemed that Clojure has "defmulti" macro corresponds to "dispatch" keyword of Xtend. Scala doesn't support but they might say that it's unnecessary because of powerful pattern matching. JRuby and Jython don't support because Ruby and Python don't support it. I'm wondering also about Kotlin but I'll end this post here because I'm full :-P

Sunday, September 2, 2012

SmileyFX: Smiley for JavaFX

Smiley ☺ is often used in graphical programs. SmileyFX is a library that allows to easily create Smiley in JavaFX. You can make a Smiley just as follows using SmileyFX:

Node smiley = SmileyFX.smiley(40);

That's it! The code creates a 40 pixel diameter (20x20xπ pixels) Smiley. Here is a perfect example in JavaFX and GroovyFX:

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.SceneBuilder;
import javafx.stage.Stage;
import smileyfx.SmileyFX;


public class JavaFXDemo extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Node smiley = SmileyFX.smiley(40);
        Scene canvas = SceneBuilder.create()
            .root(new Group(smiley))
            .width(160)
            .height(160)
            .build(); 
        
        // center align
        smiley.layoutXProperty().bind(
            canvas.widthProperty()
            .subtract(smiley.getLayoutBounds().getWidth())
            .divide(2));
        smiley.layoutYProperty().bind(
            canvas.heightProperty()
            .subtract(smiley.getLayoutBounds().getHeight())
            .divide(2));
        
        // scale by window resize
        smiley.scaleXProperty().bind(
            canvas.widthProperty()
            .divide(canvas.getWidth()));
        smiley.scaleYProperty().bind(
            canvas.heightProperty()
            .divide(canvas.getHeight()));
        
        stage.setScene(canvas);
        stage.setTitle("Smiley FX");
        stage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }

}
import static groovyx.javafx.GroovyFX.start
import static smileyfx.SmileyFX.smiley

start {
    stage(title: "Smiley FX", visible: true) {
        scene(id: "canvas", width: 160, height: 160) {
            node(smiley(40)).with {
                // center align
                layoutXProperty().bind((canvas.width() - layoutBounds.width)/2)
                layoutYProperty().bind((canvas.height() - layoutBounds.height)/2)
                // scale by window resize
                scaleXProperty().bind(canvas.width()/canvas.width)
                scaleYProperty().bind(canvas.height()/canvas.height)
            }
        }
    }
}

SmileyFX is available in here. You can use it by the follow steps:

  1. git clone https://code.google.com/p/smileyfx/
  2. cd smileyfx && ant dist

Friday, July 6, 2012

GBench 0.3.1 released!

Today I released GBench 0.3.1 with one bug fix for Groovy 2.0.

Release note: http://code.google.com/p/gbench/wiki/ReleaseNotes031.

Here is an example that compares execution time with and without @CompileStatic (new feature of Groovy 2.0) using GBench:
@Grab('com.googlecode.gbench:gbench:0.3.1-groovy-2.0') 
import gbench.BenchmarkBuilder 
import groovy.transform.CompileStatic 
 
int fib(int n) { 
    if (n < 2) return n 
    return fib(n - 1) + fib(n - 2)  
} 
 
@CompileStatic 
int fib2(int n) { 
    if (n < 2) return n 
    return fib2(n - 1) + fib2(n - 2)  
} 
 
new BenchmarkBuilder().run { 
    int n = 20  
    "Normal Version" { fib n } 
    "@CompileStatic Version" { fib2 n } 
}.prettyPrint() 
The output of the example:
Environment
===========
* Groovy: 2.0.0
* JVM: Java HotSpot(TM) 64-Bit Server VM (23.0-b21, Oracle Corporation)
    * JRE: 1.7.0_04
    * Total Memory: 98.25 MB
    * Maximum Memory: 1157.375 MB
* OS: Mac OS X (10.7.4, x86_64) 

Options
=======
* Warm Up: Auto 
* CPU Time Measurement: On

                         user  system    cpu   real

Normal Version          89945      14  89959  89961
@CompileStatic Version  39219       4  39223  39222

Wednesday, May 9, 2012

Restart Groovy life with Invokedynamic

Groovy supported invokedynamic (indy) in version 2.0 beta 3 that was released on May 7. This is a short post just to show you how to restart your Groovy life with indy. Indy is a new bytecode instruction of Java SE 7 for dynamic method invocation. If you don't know about indy, read its JSR.

Okay, let's start. First of all, install an indy-supported version of Groovy. Because indy is not supported by default for now (2.0 beta 3). You can choose which of the following ways:

* Download an archive and use a groovy-indy.jar or groovy-all-indy.jar in indy/ instead of groovy.jar in lib/ or groovy-all.jar in embeddable/.

* Build from source with an option to enable indy.

ant install -DuseIndy=true -DskipTests=true

Second, compile with an option to enable indy in a way that meets your needs as follows:

* groovy

groovy --indy YourScript.groovy

* groovyc

groovyc --indy YourScript.groovy

* GroovyShell class

import org.codehaus.groovy.control.CompilerConfiguration

def conf = new CompilerConfiguration()
conf.optimizationOptions.indy = true
def shell = new GroovyShell(conf)
shell.evaluate(/* your script */)

That's all! Have a nice Groovy life!

Friday, May 4, 2012

Exploring JavaFX 2 - Accessing application parameters

JavaFX provides Application.getParameters() as a way to access application parameters from an Application class object. For example, if a user sets a width and a height as the options and a message as an argument in GNU format:
java AccessApplicationParametersDemo --width=200 --height=100 hello
the application can receive the parameters as follows:
public class AccessApplicationParametersDemo {

    public static void main(String[] args) {
        Application.launch(UsingGetParametersApplication.class, args);
    }

}
public class UsingGetParametersApplication extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Map opts = getParameters().getNamed();
        System.out.println("width=" + opts.get("width"));
        System.out.println("height=" + opts.get("height"));
        
        List args = getParameters().getUnnamed(); 
        System.out.println("message=" + args.get(0));
    }

}
But getParameters() is not functional for now (v2.2-b06) because the option parser is poor. It does not support short form options and POSIX format and it does not allow any of the following formats:
-w=200 -h=100
--width 200 --height 100
-w 200 -h 100
Should I customize getParemters()? What do you do if you hear accessing the implementation class is hard coded in it and the method is final? I mean, it is not good choice to get options or arguments directly from getParameters() for now. I recommend that you let getParameters() to act a transporter and ask Apache Commons CLI to take the main work:
public class UsingCommonsCliApplication extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Options options = new Options();
        options.addOption("w", "width", true, "");
        options.addOption("h", "height", true, "");
        CommandLineParser parser = new PosixParser();
        CommandLine cmd = parser.parse(
            options, 
            getParameters().getRaw().toArray(
                new String[getParameters().getRaw().size()]
            )
        );
        System.out.println("width=" + cmd.getOptionValue("width")); 
        System.out.println("height=" + cmd.getOptionValue("height")); 
        System.out.println("message=" + cmd.getArgList().get(0));
    }

}
The problem might will be solved sooner or later because JavaFX team's answer to the problem is "We could consider this for a future version". In the first place, such a feature must be needed only by Applet or JWS that receives parameters in the fixed format, thus it seems better that JavaFX has application classes for those environments like AppletApplication or JWSApplication and make only them to have the feature.

Saturday, March 24, 2012

Right Groovy Benchmarking

Benchmarking Groovy or other languages that run on JVM is difficult and if you do it without much thought you will get wrong results. For example, I assume that I wrote the following program for comparing performances of StringBuilder and StringBuffer. It is well known that StringBuffer is slower because of synchronization:
def n = 100 * 1000
def at, bt

bt = System.nanoTime()
n.times {
    def sb = new StringBuilder()    
    sb.append('foo')
    sb.append('bar')
    sb.append('baz')
}
at = System.nanoTime()
println((at - bt) / n) 

bt = System.nanoTime()
n.times {
    def sb = new StringBuffer()    
    sb.append('foo')
    sb.append('bar')
    sb.append('baz')
}
at = System.nanoTime()
println((at - bt) / n) 

But the result was against expectation. StringBuffer is more than twice as fast as StringBuilder (Groovy 1.8.6、JVM 1.7.0_04-ea Server VM). It must be worse than or equal to StringBuilder even if the cost of synchronization had been written off by optimization. It means this measurement completely failed.
StringBuilder   1947.3 (2.76)
StringBuffer     703.1 (1)

The failure was more obvious by comparing between StringBuilders:
StringBuilder #1   2030.68 (4.85)
StringBuilder #2    418.47 (1)

The changes of the execution times shows us what the problem was. Some optimizations had been finished in the first time measurement and the second time measurement had started from where the optimizations were finished. Thus, the first time has a disadvantage. And there is an outstanding value in the second time measurement. The value is because of garbage collection and garbage that was collected at this time include garbage which was generated during the first time measurement. Thus, conversely, the second time has a disadvantage at this point. It means right benchmarking is what making measurements to stand on the same start line and thus we need to have finish optimization and memory cleaning before measuring.


Solving the problems by yourself is OK, but there is a benchmarking framework for Groovy, GBench. GBench 0.3.0 has got a feature to solve that tiresome problems and get correct results in place of you. The following code is a rewrite using GBench. You can get a simple report that shows only execution time by setting measureCpuTime to false for disabling measurement of CPU time:
import gbench.*

new BenchmarkBuilder().run(measureCpuTime:false) {
    'StringBuilder' {
        def sb = new StringBuilder()        
        sb.append('foo')
        sb.append('bar')
        sb.append('baz')
        sb.toString()
    }
    'StringBuffer' {
        def sb = new StringBuffer()        
        sb.append('foo')
        sb.append('bar')
        sb.append('baz')
        sb.toString()
    }
}.prettyPrint()

The result of the code was as follows. Why the difference was not so much is because my environment is Server VM and operations of locking were optimized. Jeroen Borgers' article Do Java 6 threading optimizations actually work? is a good reference for optimizations around locking:
StringBuilder   244 (1)
StringBuffer    265 (1.08)

The result of the same code with disabling the optimizations (-XX:-DoEscapeAnalysis -XX:-EliminateLocks -XX:-UseBiasedLocking) was as follows:
StringBuilder   242 (1)
StringBuffer    310 (1.28)