Java – Interpreting Java reflection performance: Why is it surprisingly very fast

interfacejavaperformancereflection

I've seen other threads saying java reflection performance is 10-100x slower than when using non-reflection calls.

My tests in 1.6 have shown that this is not the case but I found some other interesting things that I need someone to explain to me.

I have objects that implement my interface. I did three things 1) using a reference to an Object I cast that object to the interface and call the method through the interface 2) using a reference to the actual object call the method directly and 3) call the method through reflection. I saw that #1 interface call was fastest followed closely by #3 reflection but I noticed that the direct method call was the slowest by a good margin.

I don't understand that, I would've expected the direct call to be fastest, then the interface, then reflection would be much much more slow.

Blah and ComplexClass are in a different package from the main class and both have a doSomething(int x) method that implements the interface and just prints the integer x.

Here are my results (times in ms, results very similar w/ multiple trials):
calling a method directly: 107194
calling a method directly from an object cast to an interface: 89594
calling a method through reflection: 90453

Here is my code:

public class Main
{

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)
    {
        Blah x = new Blah();
        ComplexClass cc = new ComplexClass();
        test((Object) x, cc);
    }

    public static void test(Object x, ComplexClass cc)
    {
        long start, end;
        long time1, time2, time3 = 0;
        int numToDo = 1000000;
        MyInterface interfaceClass = (MyInterface) x;

        //warming up the cache
        for (int i = 0; i < numToDo; i++)
        {
            cc.doSomething(i); //calls a method directly
        }

        start = System.currentTimeMillis();
        for (int i = 0; i < numToDo; i++)
        {
            cc.doSomething(i); //calls a method directly
        }
        end = System.currentTimeMillis();
        time1 = end - start;

        start = System.currentTimeMillis();
        for (int i = 0; i < numToDo; i++)
        {
            interfaceClass.doSomething(i); //casts an object to an interface then calls the method
        }
        end = System.currentTimeMillis();
        time2 = end - start;


        try
        {
            Class xClass = x.getClass();
            Class[] argTypes =
            {
                int.class
            };
            Method m = xClass.getMethod("doSomething", argTypes);
            Object[] paramList = new Object[1];
            start = System.currentTimeMillis();
            for (int i = 0; i < numToDo; i++)
            {
                paramList[0] = i;
                m.invoke(x, paramList); //calls via reflection
            }
            end = System.currentTimeMillis();
            time3 = end - start;

        } catch (Exception ex)
        {
        }

        System.out.println("calling a method directly: " + time1);
        System.out.println("calling a method directly from an object cast to an interface: " + time2);
        System.out.println("calling a method through reflection: " + time3);
    }

Best Solution

Putting all the tests into the same program is a microbenchmarking mistake - there is a certain warm up associated with Java performance. This is the most important failing.

Put your tests in separate programs. Then run the tests several times, so you get a feeling for when warm up has finished and statistical significance.

Also you have a huge method containing your inner loop. Hotspot appears to be better at dealing with this than it used to be, but it still isn't good.

You should find that with -server calling a virtual method (even if loaded by a different class loader) in a tight loop gets completely optimised away. It therefore doesn't make much sense to say how much fast a direct call is than a reflective call.