about non-compatible optimization (was: Re: patch to bring java vtables closer to g++ abi conformance)
shudo@computer.org
shudo@computer.org
Fri Jan 25 22:30:00 GMT 2002
Bryce McKinlay <bryce@waitaki.otago.ac.nz> wrote:
> I am curious why you mentioned "dynamic invocations" or "method lookup"
> as being slow. It isn't. In fact a virtual method call (in a loop) in
> GCJ is *faster* than a static method call (in Java or C). Try it if you
> don't believe me!
It sounds curious. But I could confirm it.
I measured the time taken to invoke a method 10,000,000
times for GCJ. Java source files attached to this mail
are compiled with -O option and executed on a 600 MHz
Pentium III PC.
invokevirtual: 234 (faster than invokestatic)
invokespecial: 68
invokeinterface: 554
invokestatic: 319
(msec)
The version of GCC is as follows:
% gcj -v
...
gcc version 3.1 20020115 (Red Hat Linux Rawhide 3.1-0.18)
Kazuyuki Shudo shudo@computer.org http://www.shudo.net/
-------------- next part --------------
public class InvocationBenchmark implements InvocationBenchmarkIntf {
public final static int REPEAT = 10000000;
public int aVirtualMethod(int n) {
return n - 1;
}
private int aSpecialMethod(int n) {
return n - 1;
}
public int aInterfaceMethod(int n) {
return n - 1;
}
public static int aStaticMethod(int n) {
return n - 1;
}
public static void main(String[] args) {
InvocationBenchmark obj = new InvocationBenchmarkDerived();
benchmark(obj);
}
public static void benchmark(InvocationBenchmark obj) {
long t0, t1, t2, t3;
int n;
InvocationBenchmarkIntf intf = (InvocationBenchmarkIntf)obj;
// Invoke these methods in advance to compile them
System.out.print(obj.aVirtualMethod(1));
System.out.print(obj.aSpecialMethod(1));
System.out.print(obj.aInterfaceMethod(1));
System.out.print(obj.aStaticMethod(1));
// invokevirtual
n = REPEAT;
t0 = -System.currentTimeMillis();
while (n > 0) {
n = obj.aVirtualMethod(n);
// This invocation certainly raises a dynamic resolution of
// the callee method. This invocation may be treated as
// a static invocation if this benchmark() method is inlined
// into main() and type propagation is performed.
// But this case may not happen.
}
t0 += System.currentTimeMillis();
System.out.print(n);
// invokespecial
n = REPEAT;
t1 = -System.currentTimeMillis();
while (n > 0) {
n = obj.aSpecialMethod(n);
}
t1 += System.currentTimeMillis();
System.out.print(n);
// invokeinterface
n = REPEAT;
t2 = -System.currentTimeMillis();
while (n > 0) {
n = intf.aInterfaceMethod(n);
}
t2 += System.currentTimeMillis();
System.out.print(n);
// invokestatic
n = REPEAT;
t3 = -System.currentTimeMillis();
while (n > 0) {
n = InvocationBenchmark.aStaticMethod(n);
}
t3 += System.currentTimeMillis();
System.out.print(n);
System.out.println();
System.out.println("virtual : " + t0);
System.out.println("special : " + t1);
System.out.println("interface: " + t2);
System.out.println("static : " + t3);
System.out.println(" (msec / " + REPEAT + " times)");
}
}
-------------- next part --------------
public class InvocationBenchmarkDerived extends InvocationBenchmark {
}
-------------- next part --------------
interface InvocationBenchmarkIntf {
public int aInterfaceMethod(int n);
}
More information about the Java
mailing list