Enigmastation.com

Joseph Ottinger's blog

Java Surgery: if(s==null) {s=t} vs. s=(s==null?t:s);

From online again, names concealed to protect the guilty:

I’m trying to figure out the shortest way to do this:

Now, if you’ll pardon the stream of consciousness, through discussion it turns out he’s trying to work out the shortest form:

Or, paraphrasing in perl:

Interesting question, sort of. The “shortest form” is up to the coder, of course; why not count keystrokes if that’s what you actually care about? That said, it got me wondering: which is┬ámost efficient?

Well, my first thought is, as usual: I don’t know. I’d have to test. So that’s what I did: write two methods, one which does an if() and assigns if the expression is true, and the other which uses the ternary syntax.

I ran the expressions in a loop, 100,000 times, and ran the loops twice each (just in case warmup affected one or the other). Before we look at the times, though, here’re the expressions tested:

My first thought was that the former would be faster, because it does the assignment only if s is null. That’s the only substantive difference, really; s and t both call randomValue() before the evaluation/assignment.

The bytecode sort of looks the same way. Here’s the if() form, in bytecode:

And here’s the ternary expression:

Note the second “aload 5″ there!

Here’s the thing: this bytecode is just what’s generated from javac. It’s not what runs; JIT converts all this, and JIT optimizes. The bytecode doing more loads doesn’t mean that the executed code runs more loads, nor does it mean that a load and a store are equivalent in runtime. So looking at the bytecode is interesting, but not really very relevant – not to me, at least.

(Josh Bloch would be able to tell you a lot more about what goes on with a given bytecode block than I could. But he’d also probably not bother responding to such a simple query in the first place. Heck, even I am responding because I’m curious, and I’m willing to expose my faulty thought processes for everyone to see.)

So running the code yielded some interesting results, sort of. After a warmup, the if() ran in 70ms longer (roughly, and consistently) than the ternary expression.

I’m not surprised; my initial thought was that the opposite would happen, but hey, this is why I thought I’d test before making a declaration in the first place.

Testing always trumps assumption.

Comments?

Updated: 2010/03/26 — 8:28 am

10 Comments

Add a Comment
  1. My point is that most of the time the if() statement is clearer for the reader than the ?: statement. (Included me)

    From time to time, i end up using the ternary operator because i think that it that precise case, the code is more understandable.

    In your precise case, I think your ?: version is more complex to understand because of the affectation of s to itselft. Here it’s easy because all know what you want to do (you have written the classic if version before…). But in a project with thousand line of code, i would choose the if version…

    Then if i had a performance problem, and that by doing some metrics, it showed that the performance bottleneck is in this 100 000 iteration of if, i would try to optimise it.. And i’ll optimise more than that, like trying to do multiple iteration in the for step for exemple (so the loop overhead is less visible). I could try to inline the random calculation methods to see if the method call do not consume too much…

    In the long run, maybe, i’ll try to “precompute” the thing before in the background where the processor is idle or if it had to be computed many time with the same values, i’d try to store the results for exemple.

    All in all i would care about performance only if this function was a bottleneck anyway. Optimised code is less maintenable, less flexible. Need more time to be written.

    And optimised code need performance testing, you can’t assume for exemple that the ?: will always be faster. All depend… :

    - version of the JVM
    - processor
    - JIT optimisations
    - surrounding code
    - memory
    - …

  2. Well, I wasn’t addressing human concerns much here at all; I was just testing the “efficiency” of the different structures.

    I agree with you; the if() is clearer. Plus, 70ms over 100000 iterations doesn’t mean much, especially when you don’t know how much of that time is spent doing the evaluation vs. some of the other operations in the loop (although both loops were identical in what they did.)

    There’s lots of room for optimization even with this sample code; my goal was to examine the two options in microcosm.

    Note that I said you always had to test. :)

  3. Your tested expressions are not the same as the expressions described at the beginning of the article. In the first case you are testing the “anotherString” for null. Later you are testing “s” for null (where “t” is “anotherString”). Given the sensitivity of your test to the resulting bytecode, this probably modified your results slightly.

  4. Ack, the error was in my transcription of the question, not the tested code – but you’re right.

    That’s an interesting variation – I’ll test that, too.

  5. Okay, I just reran the test using t as the evaluation instead of s. It’s still a difference; now, though, it’s in the 30ms range for 100000 iterations instead of 70ms.

    Thank you, Frank.

  6. This will be so JVM-dependent, and might even be optimized away completely if nothing is done with the result.

  7. Caligula: Indeed, and indeed. (I was careful to actually use the result in the loop, so that it would not be thrown away, BTW.)

    Again, note that I say that YOU have to test…

  8. Completely agree with Nicolas, as years go by, I tend to priorize readable and maintainable code over performance…

  9. Come on, this is too simple, of course ternary, but don’t abuse it:

    s=(s==null?(t==null?”x”):(s==”str”?”b”:s+”c”);

  10. Why does this question come up so frequently? Performance-wise, if this is all you need to optimize then you are likely the most skilled programmer on the planet having solved all the problems of algorithm, i/o, and memory optimization

Leave a Reply

Enigmastation.com © 2014 Frontier Theme
%d bloggers like this: