InstanceOf Performance

From EggeWiki
Jump to: navigation, search

The following is a microbenchmark to test the performance of the Java instanceOf operation. The four dispatch methods tested are:

  1. InstanceOf operator
  2. Comparing class objects using ==
  3. Using polymorphism to dispatch
  4. Embedding a type id into each class.
package org.egge;
 
public class InstanceOf {
 
	private static final int REPS = 1000000000;
 
	private enum Type {
		A, B
	};
 
	private static abstract class Base {
		int sum;
		final Type type;
 
		public Base(Type type) {
			this.type = type;
		}
 
		public abstract void doSomthing();
	}
 
	private static class A extends Base {
		public A() {
			super(Type.A);
		}
 
		public void doA() {
			sum += 2;
		}
 
		@Override
		public void doSomthing() {
			sum += 2;
		}
	}
 
	private static class B extends Base {
		public B() {
			super(Type.B);
		}
 
		public void doB() {
			sum -= 2;
		}
 
		@Override
		public void doSomthing() {
			sum -= 2;
		}
	}
 
	public static void main(String[] args) {
		for (int i = 0; i < 5; i++) {
			System.out.println("Rep " + i);
			for (Type t : Type.values()) {
				Base base;
				if (t == Type.A) {
					base = new A();
				} else {
					base = new B();
				}
				testInstanceOf(base);
				testIsClass(base);
				testOO(base);
				testId(base);
			}
		}
	}
 
	private static void testInstanceOf(Base base) {
		long start = System.currentTimeMillis();
		for (int i = 0; i < REPS; i++) {
			if (base instanceof A) {
				((A) base).doA();
			} else if (base instanceof B) {
				((B) base).doB();
			} else {
				throw new RuntimeException();
			}
		}
		long diff = System.currentTimeMillis() - start;
		System.out.println("InstanceOf " + diff + " " + base.sum);
	}
 
	private static void testOO(Base base) {
		long start = System.currentTimeMillis();
		for (int i = 0; i < REPS; i++) {
			base.doSomthing();
		}
		long diff = System.currentTimeMillis() - start;
		System.out.println("OO " + diff + " " + base.sum);
	}
 
	private static void testId(Base base) {
		long start = System.currentTimeMillis();
		for (int i = 0; i < REPS; i++) {
			switch (base.type) {
			case A:
				((A) base).doA();
				break;
			case B:
				((B) base).doB();
				break;
			default:
				throw new RuntimeException();
			}
		}
		long diff = System.currentTimeMillis() - start;
		System.out.println("Id " + diff + " " + base.sum);
	}
 
	private static void testIsClass(Base base) {
		long start = System.currentTimeMillis();
		for (int i = 0; i < REPS; i++) {
			if (base.getClass() == A.class) {
				((A) base).doA();
			} else if (base.getClass() == B.class) {
				((B) base).doB();
			} else {
				throw new RuntimeException();
			}
		}
		long diff = System.currentTimeMillis() - start;
		System.out.println("class== " + diff + " " + base.sum);
	}
 
}

The results are significantly different when running on a Solaris server JVM vs a Windows client JVM. On the server, the results of the four methods are nearly identical. The interesting thing with the server is the first iteration runs very quickly. This is because only one type has been loaded at that point and the operations can easily be optimized, and there's only one possible path. The results on Windows, show the fastest method is comparing class objects, then instanceof, then polymorphism, and lastly the type id.

Results

Invalid language.

You need to specify a language like this: <source lang="html4strict">...</source>

Supported languages for syntax highlighting:

4cs, 6502acme, 6502kickass, 6502tasm, 68000devpac, abap, actionscript, actionscript3, ada, algol68, apache, applescript, apt_sources, asm, asp, autoconf, autohotkey, autoit, avisynth, awk, bascomavr, bash, basic4gl, bf, bibtex, blitzbasic, bnf, boo, c, c_loadrunner, c_mac, caddcl, cadlisp, cfdg, cfm, chaiscript, cil, clojure, cmake, cobol, coffeescript, cpp, cpp-qt, csharp, css, cuesheet, d, dcs, delphi, diff, div, dos, dot, e, ecmascript, eiffel, email, epc, erlang, euphoria, f1, falcon, fo, fortran, freebasic, fsharp, gambas, gdb, genero, genie, gettext, glsl, gml, gnuplot, go, groovy, gwbasic, haskell, hicest, hq9plus, html4strict, html5, icon, idl, ini, inno, intercal, io, j, java, java5, javascript, jquery, kixtart, klonec, klonecpp, latex, lb, lisp, llvm, locobasic, logtalk, lolcode, lotusformulas, lotusscript, lscript, lsl2, lua, m68k, magiksf, make, mapbasic, matlab, mirc, mmix, modula2, modula3, mpasm, mxml, mysql, newlisp, nsis, oberon2, objc, objeck, ocaml, ocaml-brief, oobas, oracle11, oracle8, oxygene, oz, pascal, pcre, per, perl, perl6, pf, php, php-brief, pic16, pike, pixelbender, pli, plsql, postgresql, povray, powerbuilder, powershell, proftpd, progress, prolog, properties, providex, purebasic, pycon, python, q, qbasic, rails, rebol, reg, robots, rpmspec, rsplus, ruby, sas, scala, scheme, scilab, sdlbasic, smalltalk, smarty, sql, systemverilog, tcl, teraterm, text, thinbasic, tsql, typoscript, unicon, uscript, vala, vb, vbnet, verilog, vhdl, vim, visualfoxpro, visualprolog, whitespace, whois, winbatch, xbasic, xml, xorg_conf, xpp, yaml, z80, zxbasic


Windows:
InstanceOf 6141 
class== 3312
OO 8547 
Id 9953

Solaris first:
InstanceOf 121 
class== 122 
OO 114 
Id 119 

Solaris last:
InstanceOf 3156 
class== 2925 
OO 3083 
Id 3067
Personal tools