Okay, so let it first be known that I’m pretty much a Java newb. I used the language a few times in school, and picked up some more of it for basic Android coding. But it wasn’t until I started my most recent job that it’s become my go-to language. Teams at Amazon are given a lot of leeway to choose their tools and the team I’m on uses primarily Perl and Java for its day-to-day coding needs.

So I was working on some code today that was showing a strangely bimodal run time. It ran “Quickly” most of the time, “Average” a little bit of the time, and “God Awful Slow Oh Sweet Jesus Why Isn’t It Done Yet” the rest of the time.

After some poking around and eventually consulting the local Java internals guru, I figured out the problem (example has been sanitized so that I still have a job on Monday):

private ThreadSafeObject tso;
...
public void synchronized timeMethod()
{
    if(tso != null)
    {
        tso.doWork();
        tso = null;
    }
}

It turns out that what was happening was that, since ThreadSafeObject is natively thread safe, there was some strange juggling going on between the Synchronized method and the ThreadSafeObject’s thread safety mutex. Basically timeMethod() ended up waiting on two sets of mutexes, which sometimes entailed a performance hit. It first had to wait on the mutex required to enter the synchronized method and then, on executing the first line of that method, had to wait for the mutex protecting the thread safety of ThreadSafeObject t.

Now it’s unclear to me exactly why this performance hit ended up being so bimodal. Perhaps someone with stronger Java-fu can help be on that point. But when the synchronized keyword above was removed, performance improved greatly and the strange bimodality of the performance profile disappeared.

Lesson: beware of synchronizing code that doesn’t need it. Not only are you losing performance for nothing, but sometimes the performance hits can be both great and strange.


Disclosure Notice