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 don’t 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.
1. 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%.“
2. 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. Also see Garbage-First Collector(G1) in Java 7.
3. 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 as well:
- Java Concurrency in Practice
- The Art of Multiprocessor Programming
- Concurrent Programming in Java: Design Principles and Pattern (2nd Edition)
4. 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.
5. 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, don’t 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.
jstat -J-Djstat.showUnsupported=true -snap PID | grep _sync_
There are so much to say on this subject, but i don’t have time to write more right now. Happy coding!
Related Articles :
Bulletproof Java Code: A Practical Strategy for Developing Functional, Reliable, and Secure Java Code
Use Java? If you do, you know that Java software can be used to drive application logic of Web services or Web applications. Perhaps you use it for desktop applications? Or, embedded devices? Whatever your use of Java code, functional errors are the enemy!
To combat this enemy, your team might already perform functional testing. Even so, you're taking significant risks if you have not yet implemented a comprehensive team-wide quality management strategy. Such a strategy alleviates reliability, security, and performance problems to ensure that your code is free of functionality errors.Read this article to learn about this simple four-step strategy that is proven to make Java code more reliable, more secure, and easier to maintain.