Skip to main content

Closure and performance

Posted by forax on August 24, 2006 at 8:09 AM EDT

I've read the proposal about function types and closures and i have noticed that the invocation of a function type will use the newly introduced bytecode invokedynamic (the gilad blog about invokedynamic) and i think i know why !

So let me introduce a small example of closure, the method transform applies a transformation on each item of an array and store the result in the same array.
The transformation is specified using a function type typed CharSequence(CharSequence) i.e. a function that takes a CharSequence and returns a CharSequence.

  static CharSequence[] transform(CharSequence(CharSequence) transformation,CharSequence... array) {
    for(int i=0;i<array.length;i++) {
      array[i]=transformation(array[i]);
    }
    return array;
  }

The following code applies an identity transformation :

  CharSequence(CharSequence) identity = (CharSequence seq) {return seq; };
  CharSequence[] seqs=transform(identity,"2","3");
  System.out.println(Arrays.toString(seqs));

So why closure can't use a classical call (invokevirtual) instead of a invokedynamic call, because the proposal defines subtyping rules between closures.
It is possible to use a function type with not exactly the same type the the one defined. In our example, the declared signature is CharSequence(CharSequence seq), one can use instead a closure typed, by example, String(Object).

  String(Object) bang = (Object o) {return "!"+o; };
  CharSequence[] seqs2=transform(bang,"2","3");
  System.out.println(Arrays.toString(seqs2));

So in the method transform, the call to transformation can call a function type with a different signature that the one declared, that's why invokedynamic must be used here.

So why using invokedynamic is important, it's because it can hurt performance, invoking a method without the same signature is more complex than a simple call.
In C#, a delegate method call (a roughly equivalent to closure) is more expensive than a method call.
Note that this is a special case of invokedynamic, there is only one method that is applicable for a specific closure so a smart VM can optimise this case.

Related Topics >>