package mikera.vectorz.performance; import com.google.caliper.Runner; import com.google.caliper.SimpleBenchmark; /** * Benchmark to test the difference between interface and virtual dispatch. * * This motivates preferring "AVector" to "IVector" where possible to obtain * polymorphic behaviour in the Vectorz library. * * Example results: * * 0% Scenario{vm=java, trial=0, benchmark=Interface} 13.04 ns; σ=0.19 ns @ 10 trials * 50% Scenario{vm=java, trial=0, benchmark=Virtual} 7.39 ns; σ=0.26 ns @ 10 trials * * benchmark ns linear runtime * Interface 13.04 ============================== * Virtual 7.39 ================= * * vm: java * trial: 0 * @author Mike * */ public class InterfaceVsVirtualBenchmark extends SimpleBenchmark { public static interface I { public long foo(Long a); } public static class A implements I { public long foo(Long a) { return a+1; } } public static class B extends A { @Override public long foo(Long a) { return a+2; } } public static class C extends A implements Cloneable { @Override public long foo(Long a) { return a+3; } } public static class D implements Cloneable, I { @Override public long foo(Long a) { return a+3; } } public A a=new A(); public B b=new B(); public C c=new C(); public D d=new D(); public static long output=0; public I getInterfaceObject(int i) { switch (i&3) { case 0: return a; case 1: return b; default: return d; } } public A getVirtualObject(int i) { switch (i&3) { case 0: return a; case 1: return b; default: return c; } } public void timeInterface(int runs) { output=0; for (int i=0; i<runs; i++) { I object=getInterfaceObject(i); output+=object.foo((long)i); } } public void timeVirtual(int runs) { output=0; for (int i=0; i<runs; i++) { A object=getVirtualObject(i); output+=object.foo((long)i); } } // performance test stub public static void main(String[] args) { new InterfaceVsVirtualBenchmark().run(); } private void run() { Runner runner=new Runner(); runner.run(new String[] {this.getClass().getCanonicalName()}); } }