Java Application Performance Management
Posted by Anandhan Subbiah on Oct 4, 2007 in Java, Programming Concepts, Technical Articles • 1 commentJava Application Performance Management is not performance tuning but a software process which is applied throughout the development of a product. The benefit of this approach is simply “saving dollars”. The cost and time required to fix a performance issue in production will be a lot more than in development. There is always the human element as well developers will be able to solve issues faster and more effectively in development when nothing is on fire yet.
The best way of doing this is integrating SLA’s into requirements. The SLA as important it is must be a realistic figure based on the nature of the product , the load , the size of the data and the effect of various parameters.
There are standard development methodologies too which can help in determining issues faster.
• Code Profiling
• Code Coverage.
It is very important to know why certain areas in the code are not exercised. Profiling will help understand memory leaks and in general how well the application behaves under load.
The SLA’s should also extend into QA. The QA team should know the response time in advance and they should fail a test if the response times do not match. This in terms requires a QA environment which is similar to production or there should be at least some decent formulae can relate production response times to QA response times.
Another important factor is the behavior of the system under load. If 1000 users is the projected user load then the application should be tested at least with 1500 users. If the system barely handles 1000 users then that should be a huge case for concern
Performance tuning is invaluable but only if it was performed against load that reflects real-world usage patterns. Predicting exactly what your users will do and how they will use your application before you present it to them is impossible, but detailed analysis of use cases can increase your predictions’ accuracy.
The most common and relevant performance metrics are end-user response time, request throughput, resource utilization, and application availability.
Memory Management
This is the most important aspect so I am focusing on this more and it is an art by itself. Unlike C++, Java handles Garbage collection implicitly. The Sun JVM heap is divided into two parts
• Old generation ( tenured space)
• New generation ( young space)
The New generation is further divided into Eden space and two survivor spaces “to” and “from”.
There are two types of garbage collection minor and major. Minor GC’s are not bad for the application but major GC’s are bad as they cause the JVM to freeze.
All temporary objects are created in the Eden space and when it gets full a minor garbage collection happens which removes items with no references and moves referenced items from Eden space to the From space . This way the short-lived items are removed without a exhaustive GC cycle .When the Eden space gets full then the items are moved from the “From space” to the “To Space.”. At any point in time only one survivor space has data. The next time Eden space gets full the items in the “To space” are moved to the tenured space and items with references in the Eden space are moved to the “From space”. This works very well to remove temporary objects without a major GC.
When the Eden space becomes full again a full GC happens which does a complete GC by doing reachability test. The reachability test results in the marking of live objects in the heap that is followed by a sweep of dead objects and an optional compaction to defray the heap. The JVM accomplishes this by doing a heavy processor intensive mark and sweep. It scans through the complete JVM and marks all items without a reference and then in the second scan removes all items marked for deletion.
The best configuration for heap size from my experience should be
• Young space should be slightly less than 1/2 of the total heap space
• The survivor spaces should be 1/8 of the Young space
So for a 2GB heap space the best configuration for an application with heavy load will be
-Xmx2048m -Xms2048m -XX:MaxNewSize=896m -XX:NewSize=896m -XX:SurvivorRatio=6
–XmxNNNm Maximum size of the heap, where NNN represents the size of the heap, and m represents the units (m=megabytes, g=gigabytes)
–XmsNNNm Minimum size of the heap, which I suggest should be equal to the maximum size
–XX:MaxNewSize=NNN m Maximum size of the young (or new) generation
–XX:NewSize=NNN Minimum size of the young (or new) generation
–XX:SurvivorRatio=n Size of the survivor spaces as a ratio of its relationship to the size of Eden
The behavior of the heap can be found better by enabling verbose garbage collections
–verbose:gc => Enables verbose garbage collection
–Xloggc:filename => Prints garbage collection information to a log file
–XX:+PrintGCDetails => Prints garbage collection details, such as the size of the young and old generations before and after the garbage collection, the size of the total heap, the time length of the garbage collection in both generations, and the size of objects promoted at every garbage collection
–XX:+PrintGCTimeStamps => Adds timestamp information to garbage collection details
–XX:+PrintHeapAtGC => Prints detailed garbage collection information, including heap occupancy before and after garbage collection
–XX:+PrintTenuringDistribution => Prints object aging or tenuring information, which helps you tune the sizes of the generations, Eden, and the two survivor spaces
–XX:+PrintHeapUsageOverTime => Prints heap usage and capacity with timestamps
–XX:+PrintTLAB => Print thread local allocation buffers (TLAB) information

Great article.
Here is another one I liked about Java APM:
Application Performance Management