# Thursday, 30 March 2006
« Rotor 2.0 released | Main | @ikvm.lang.Internal »
A Micro Optimization

Yesterday I thought of a potential micro optimization for the generated CIL code. Since I'm now tracking method invocations on the this reference, it is possible to devirtualize calls to final methods or methods that are provably not overridden. I didn't expect too much from this optimization, because I assumed that the .NET JIT is capable of doing the same optimization and so the only effective difference would be the removal of the explict null check of the this reference.

After implementing the optimization I wrote a micro benchmark:

final class perf {
  public static void main(String[] args) {
    perf p = new perf();
    p.runTest();
  }
  private void runTest() {
    long start = System.currentTimeMillis();
    for (int i = 0; i < 1000000000; i++) {
      equals(null);
    }
    long end = System.currentTimeMillis();
    System.out.println(end - start);
  }
}

Here are the results:

  Time (ms)
IKVM 0.26 10806
IKVM 0.27 1883
JDK 1.1 4597
JDK 1.5 Client VM 12068
JDK 1.5 Server VM 0


Somewhat to my surprise neither JDK 1.5 Client VM nor the .NET Framework JIT realised that the virtual method invocation could be devirtualized. Unsurprisingly, HotSpot Server VM was able to deduce that the loop didn't actually do anything at all and optimize it away entirely.

I also threw in JDK 1.1, because as usual in microbenchmarks it outperforms HotSpot Client VM.

Note that the use of the equals method in the benchmark is not very significant, it's just a placeholder for a simple method that can easily be inlined. This optimization is most significant for simple property getters that can be inlined.

The code for this optimization is not yet in cvs.

Oops

On a more embarrassing note, doing this optimization also revealed a hole in the object model remapping. Throwable doesn't properly inherit all the Object methods. The code that gets generated works correctly (in most cases), but it is not verifiable. Here's an example of something that is currently broken:

public class test extends Throwable {
  public static void main(String[] args) throws Exception {
    test c = new test() {
      protected Object clone() {
        return "OK";
      }
    };
    System.out.println(c.clone());
  }
}

Running this on IKVM throws a CloneNotSupportedException instead of printing OK.

Thursday, 30 March 2006 11:08:03 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
Thursday, 30 March 2006 18:24:44 (W. Europe Daylight Time, UTC+02:00)
I remember that there was some problem with making a non-virtual call to a virtual method in .NET when run through PEVerify. IIRC, the NHibernate team used the HashCodeProvider assembly that was using this method to non-virtually call the Object.GetHashCode() method.

Is there another way of doing it besides doing an IL "call" to the base method in question?
Name
E-mail
Home page

I apologize for the lameness of this, but the comment spam was driving me nuts. In order to be able to post a comment, you need to answer a simple question. Hopefully this question is easy enough not to annoy serious commenters, but hard enough to keep the spammers away.

Anti-Spam Question: What method on java.lang.System returns an object's original hashcode (i.e. the one that would be returned by java.lang.Object.hashCode() if it wasn't overridden)? (case is significant)

Answer:  
Comment (HTML not allowed)  

Live Comment Preview