2

Look at this piece of code:

MessageParser parser = new MessageParser();
for (int i = 0; i < 10000; i++) {
    parser.parse(plainMessage, user);
}

For some reason, it runs SLOWER (by about 100ms) than

for (int i = 0; i < 10000; i++) {
    MessageParser parser = new MessageParser();
    parser.parse(plainMessage, user);
}

Any ideas why? The tests were repeated a lot of times, so it wasn't just random. How could creating an object 10000 times be faster than creating it once?

4
  • 2
    100ms slower over how long a run? Commented Sep 27, 2009 at 19:19
  • show full test code and warmup threshold... Commented Sep 27, 2009 at 22:05
  • It runs only once, for about 350ms on my laptop... and I'm not trying to fix performance, I want to know why this difference is counter-intuitive. Commented Sep 28, 2009 at 11:37
  • In summary, the compiler & GC have more Man Brain Hours in it than you will have available to you in your lifetime. Never assume you can out-think it--always write your code to be as readable as possible and leave the rest to the compiler. Commented Mar 12, 2010 at 17:46

4 Answers 4

10

Because Java has 'generational garbage collection' and can quickly identify (in the loop) that it doesn't re-use the same object/memory space, so the GC cost is virtually nil. On the other hand, your long-lived object will survive a generational pass over the nursery generation and have to be moved out to the main generation.

In summary, you can't really assume about performance without doing tests to measure it in place.

Sign up to request clarification or add additional context in comments.

4 Comments

Later JVMs also do escape analysis: they work out which objects do not escape from a block or method and allocate those on the stack, not on the heap. The MessageParser declared inside the for loop is an easy candidate for that optimisation. Depending on how complex the method is, the MessageParser declared outside the for loop might not be.
No assumptions being made... this isn't even my actual use-case. I posted it because I curious as to why :D
@AlBlue so then the cost of checking if an object is garbage collectible is actually less than re-creating it?
Objects that are dead (not reachable) in the nursery generation can be thrown away en-masse rather than one at a time. What happens is that the objects which survive a GC gen pass will be promoted into the main heap, which can take some time. In your first example, that's what will happen which may explain the extra hit. (In both cases, it will need to find out if the object is reachable or not anyway). You can see what's happening with java -verbose:gc if you're interested.
0

There may be some logic to clean up the internal state on a subsequent call to parser.

Did the GC run during your benchmark? It's fairly cheap to instantiate a new object, and it's not a fair comparison if you don't count the time to dispose of all of the objects you created in the faster case.

Comments

0

I have no idea what MessageParser does or where it comes from. It may be "leaking" internally. Another possibility is that the object become further away from the data created during the parsing. This means you are likely to get a TLA miss. Also if the the MessageParser keeps internal state, and moves into the tenured generation the GC mechanics of noting that it references new data can be a problem ("card scoring" is jargon that pops to mind).

1 Comment

The parser has no internal state... just runs a checks if the given string starts with '/' (using startsWith) and returns.
0

What happens if you benchmark the first example while restricting the scope of parser, ie

{
    MessageParser parser = new MessageParser();
    for (int i = 0; i < 10000; i++) {
        parser.parse(plainMessage, user);
    }
}
// `parser` no longer visible

I'd expect this to be fastest as only one object has to be created, and the VM still knows that parser can be gc'd immediately after the loop.

1 Comment

Thats how it is right now in both test cases... both are in their own block.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.