Skip to main content

Java Reflection Performance



Does creating an object using reflection rather than calling the class constructor result in any significant performance differences?




Comments

  1. Yes - absolutely. Looking up a class via reflection is, by magnitude, more expensive.

    Quoting Java's documentation on reflection:


    Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.


    Here's a simple test I hacked up in 5 minutes on my machine, running Sun JRE 6u10:

    public class Main {

    public static void main(String[] args) throws Exception
    {
    doRegular();
    doReflection();
    }

    public static void doRegular() throws Exception
    {
    long start = System.currentTimeMillis();
    for (int i=0; i<1000000; i++)
    {
    A a = new A();
    a.doSomeThing();
    }
    System.out.println(System.currentTimeMillis() - start);
    }

    public static void doReflection() throws Exception
    {
    long start = System.currentTimeMillis();
    for (int i=0; i<1000000; i++)
    {
    A a = (A) Class.forName("misc.A").newInstance();
    a.doSomeThing();
    }
    System.out.println(System.currentTimeMillis() - start);
    }
    }


    With these results:

    35 // no reflection
    465 // using reflection


    Bear in mind the lookup and the instantiation are done together, and in some cases the lookup can be refactored away, but this is just a basic example.

    Even if you just instantiate, you still get a performance hit:

    30 // no reflection
    47 // reflection using one lookup, only instantiating


    Again, YMMV.

    ReplyDelete
  2. There is some overhead with reflection, but it's a lot smaller on modern VMs than it used to be.

    If you're using reflection to create every simple object in your program then something is wrong. Using it occasionally, when you have good reason, shouldn't be a problem at all.

    ReplyDelete
  3. Yes, it's slower.

    But remember the damn #1 rule--PREMATURE OPTIMIZATION IS THE ROOT OF ALL EVIL

    (Well, may be tied with #1 for DRY)

    I swear, if someone came up to me at work and asked me this I'd be very watchful over their code for the next few months.

    You must never optimize until you are sure you need it, until then, just write good, readable code.

    Oh, and I don't mean write stupid code either. Just be thinking about the cleanest way you can possibly do it--no copy and paste, etc. (Still be wary of stuff like inner loops and using the collection that best fits your need--Ignoring these isn't "unoptimized" programming, it's "bad" programming)

    It freaks me out when I hear questions like this, but then I forget that everyone has to go through learning all the rules themselves before they really get it. You'll get it after you've spent a man-month debugging something someone "Optimized".

    EDIT:

    An interesting thing happened in this thread. Check the #1 answer, it's an example of how powerful the compiler is at optimizing things. The test is completely invalid because the non-reflective instantiation can be completely factored out.

    Lesson? Don't EVER optimize until you've written a clean, neatly coded solution and proven it to be too slow.

    ReplyDelete
  4. You may find that A a = new A() is being optimised out by the JVM.
    If you put the objects into an array, they don't perform so well. ;)
    The following prints...

    new A(), 141 ns
    A.class.newInstance(), 266 ns
    new A(), 103 ns
    A.class.newInstance(), 261 ns

    public class Run {
    private static final int RUNS = 3000000;

    public static class A {
    }

    public static void main(String[] args) throws Exception {
    doRegular();
    doReflection();
    doRegular();
    doReflection();
    }

    public static void doRegular() throws Exception {
    A[] as = new A[RUNS];
    long start = System.nanoTime();
    for (int i = 0; i < RUNS; i++) {
    as[i] = new A();
    }
    System.out.printf("new A(), %,d ns%n", (System.nanoTime() - start)/RUNS);
    }

    public static void doReflection() throws Exception {
    A[] as = new A[RUNS];
    long start = System.nanoTime();
    for (int i = 0; i < RUNS; i++) {
    as[i] = A.class.newInstance();
    }
    System.out.printf("A.class.newInstance(), %,d ns%n", (System.nanoTime() - start)/RUNS);
    }
    }


    This suggest the difference is about 150 ns on my machine.

    ReplyDelete
  5. "Significant" is entirely dependent on context.

    If you're using reflection to create a single handler object based on some configuration file, and then spending the rest of your time running database queries, then it's insignificant. If you're creating large numbers of objects via reflection in a tight loop, then yes, it's significant.

    In general, design flexibility (where needed!) should drive your use of reflection, not performance. However, to determine whether performance is an issue, you need to profile rather than get arbitrary responses from a discussion forum.

    ReplyDelete
  6. Yes, it is significantly slower. We were running some code that did that, and while I don't have the metrics available at the moment, the end result was that we had to refactor that code to not use reflection. If you know what the class is, just call the constructor directly.

    ReplyDelete
  7. If there really is need for something faster than reflection, and it's not just a premature optimization, then bytecode generation with ASM or a higher level library is an option. Generating the bytecode the first time is slower than just using reflection, but once the bytecode has been generated, it is as fast as normal Java code and will be optimized by the JIT compiler.

    Some examples of applications which use code generation:


    Invoking methods on proxies generated by CGLIB is slightly faster than Java's dynamic proxies, because CGLIB generates bytecode for its proxies, but dynamic proxies use only reflection (I measured CGLIB to be about 10x faster in method calls, but creating the proxies was slower).
    JSerial generates bytecode for reading/writing the fields of serialized objects, instead of using reflection. There are some benchmarks on JSerial's site.
    I'm not 100% sure (and I don't feel like reading the source now), but I think Guice generates bytecode to do dependency injection. Correct me if I'm wrong.

    ReplyDelete
  8. Be careful of the benchmarks posted above! They are flawed. See this post: http://stackoverflow.com/questions/647111/newinstance-vs-new

    ReplyDelete
  9. Yes, always will be slower create an object by reflection because the JVM cannot optimize the code on compilation time. See the Sun/Java Reflection tutorials for more details.

    See this simple test:

    public class TestSpeed {
    public static void main(String[] args) {
    long startTime = System.nanoTime();
    Object instance = new TestSpeed();
    long endTime = System.nanoTime();
    System.out.println(endTime - startTime + "ns");

    startTime = System.nanoTime();
    try {
    Object reflectionInstance = Class.forName("TestSpeed").newInstance();
    } catch (InstantiationException e) {
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
    endTime = System.nanoTime();
    System.out.println(endTime - startTime + "ns");
    }
    }

    ReplyDelete
  10. Often you can use Apache commons BeanUtils or PropertyUtils which introspection (basically they cache the meta data about the classes so they don't always need to use reflection).

    ReplyDelete
  11. Reflection is slow, though object allocation is not as hopeless as other aspects of reflection. Achieving equivalent performance with reflection-based instantiation requires you to write your code so the jit can tell which class is being instantiated. If the identity of the class can't be determined, then the allocation code can't be inlined. Worse, escape analysis fails, and the object can't be stack-allocated. If you're lucky, the JVM's run-time profiling may come to the rescue if this code gets hot, and may determine dynamically which class predominates and may optimize for that one.

    Be aware the microbenchmarks in this thread are deeply flawed, so take them with a grain of salt. The least flawed by far is Peter Lawrey's: it does warmup runs to get the methods jitted, and it (consciously) defeats escape analysis to ensure the allocations are actually occurring. Even that one has its problems, though: for example, the tremendous number of array stores can be expected to defeat caches and store buffers, so this will wind up being mostly a memory benchmark if your allocations are very fast. (Kudos to Peter on getting the conclusion right though: that the difference is "150ns" rather than "2.5x". I suspect he does this kind of thing for a living.)

    ReplyDelete
  12. In the doReflection() is the overhead because of Class.forName("misc.A") (that would require a class lookup, potentially scanning the class path on the filsystem), rather than the newInstance() called on the class. I am wondering what the stats would look like if the Class.forName("misc.A") is done only once outside the for-loop, it doesn't really have to be done for every invocation of the loop.

    ReplyDelete
  13. Interestingly enough, settting setAccessible(true), which skips the security checks, has a 20% reduction in cost.

    Without setAccessible(true)

    new A(), 70 ns
    A.class.newInstance(), 214 ns
    new A(), 84 ns
    A.class.newInstance(), 229 ns


    With setAccessible(true)

    new A(), 69 ns
    A.class.newInstance(), 159 ns
    new A(), 85 ns
    A.class.newInstance(), 171 ns

    ReplyDelete
  14. I came across this question because I've been wondering about the performance of a lot of the server software I've been working with. And I mean vendor software from some very large vendors. I too, had read on Sun's and other sites about avoiding reflection code because of performance. Yet more and more I'm seeing large server software which is extensively based on reflection and incorporates layers and layers of the stuff. Presumably to adhere to things such as decoupling principles and dynamically generating code from drag and drop development GUIs.

    Is this really an issue or am I just worrying about nothing? :-)

    ReplyDelete
  15. The benchmark in the top answer is badly flawed. The non-reflective instantiation of A() will likely be eliminated by the JVM as dead code - meaning you are simply benchmarking the loop and not object instantiation.

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex