Ever had performance problems? Yeah me too. If my manager screams “faaaaster” one more time, i will have hearing impairment for the rest of my life. BTW, did i sense a german pronunciation in all that noise?
Can you believe that there are still people doing ignorant trash talk about the garbage collector (get it?) and performance of the JVM..
… i will go back writing C again so i dont have to worry about performance…
The JVM is continuously improving its collector algorithms and highly sophisticated optimizations are incorporated into the compiler with every release (and have been doing so for the last 10 years). Do *you* really expect to have the experience, ability and time to write better and more optimized C code than some of the smartest people on this earth?
If you are like me and 99.99 percent rest of us, you be wise to forget about C. Just get over it. (salute to all hardcore C programmers, do not feel provoked)
As much as us developers love abstractions, we cannot deny the fact that they are inherently leaky. Hardware *does* matter. The trend of processor count and memory growth make shared memory thread concurrency a lot harder. Locking, context switching and thread scheduling can make your throughput equal to syrup, thinking that pouring more threads into your shiny new super-beefy-machine will somehow magically will give you more performance. It probably will to some degree, but that’s not my point.
So what to do? I do not claim to be a performance expert, i am not, but i have some practical advice that at least helped me squash some nasty performance bugs in the past.
- Write clean and “dumb” code. Consider making your classes immutable, they are thread-safe hence no need for synchronization and can be cached with confidence that object values do not change after being created. Immutability also leads to code that is easier to understand. Do not try to outsmart the JVM with premature optimization tricks.
Donald Knuth said: “Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.“
- Spend some time on understanding the how different garbage collectors works. The information is a bit scattered, but its out there. Find the resource sharing sweet-spot between garbage collection and your application. Generally speaking larger heaps means garbage collector needs to work harder (stealing more CPU cycles) and pauses will be longer, but less frequent. In my experience you cannot avoid stop-the-world pauses from happening, even using CMS, because eventually your heap will be fragmented as swiss cheese, and boom, memory fragmentation failure. The good news is that JDK7 will probably include a new low-pause collector, called G1, which can potentially fully avoid stop-the-world pauses. UPDATE: See Grabage-First Collector(G1) in Java 7.
- Always use java.util.concurrency by default when programming. Read the Java Memory Model and Thread Specification. It will help you understand why your code may not performing as it should. There are very good books on the subject of concurrency aswell:
- Chances are that you are dealing with legacy code (you cannot influence) that have coarse grained synchronization, causing high thread contention. Using CPU affinity with multiple JVM processes on the same machine can help reduce contention for hot locks.
- If you think you found JVM performance problems by doing benchmarks, first, make sure you know that you *know* your measurements are accurate. If you try measure something, dont measure other stuff. Ignoring this advice may mislead you from where the real problems lurk. So make sure to properly isolate system parts before you start measuring.
For example, if you suspect thread contention, have a look at ThreadInfo or try jstat and look for sun.rt._sync_ContendedLockAttempts.
[java]jstat -J-Djstat.showUnsupported=true -snap PID | grep _sync_[/java]
There are so much to say on this subject, but i dont have time to write more right now. Happy coding!