Tuesday, August 12, 2014

Java Performance Monitoring and Testing

After a couple of months gap, I am continuing this blog. This time, the topic is not about development, this is a bit complicated but interesting topic, and I have spent quite a lot of time for performance monitoring in java.

Java is very popular programming language and we can develop any type of application from desktop, web, mobile, embedded and many more. The use of advanced IDE's (Eclipse for example) make the development process very fast, easy and with a lot of customization preferred by developer. The software development, nowadays, is so fast that most of the time, we forget about performance that is how well and how consistently the application works for the long run after deploying. 

We have to deploy applications which has to run for several months or even several years! To make the development process faster, we use a lot of third party libraries which might not have been fully tested to work for long run. Sometimes, we program incorrectly, or we forget to properly manage the created objects, which actually affects the application for long run, for example, memory leak. It is the most prevalent issue found in applications which run for  a long time. This article does not go deep into performance analysis theory, but gives quick idea on how performance analysis in java is carried out using available tools.

1) JConsole

JConsole is a simple performance monitoring tool which displays alot of useful information of a running java application. I am using Java 1.7 and JConsole is included in this version. You have to be sure, I guess old java version do not support JConsole, if that happens, you have to upgrade you java.

For local testing, its really straight forward, JConsole provides list of java applications and we have to select one. Then JConsole displays memory, threads, classes related to that application. A nice presentation of these information in graph or table, makes it easy to see if there is any subtle performance problem. If we let it running for long time, we can easily notice if there is any memory leak or system problem with heavy consumption of processor by the application, maybe my huge number of threads creation.

   Fig:   JConsole

We can remotely connect to the application running in different system through network. For that we have to enable Remove Management and Monitoring Service (JMX) in JVM. If you are running tomcat, its rather straight forward. We just append the following text in the setenv.sh file in $CATALINA_BASE directory.

export CATALINA_OPTS="-Dcom.sun.management.jmxremote
                                               -Dcom.sun.management.jmxremote.port=
                                               -Dcom.sun.management.jmxremote.authenticate=false
                                               -Dcom.sun.management.jmxremote.ssl=false
                                               -Djava.rmi.server.hostname="


If you want to increase heap memory size, you can append the following line.(this is optional)

export CATALINA_OPTS="$CATALINA_OPTS -Xms512m"

export CATALINA_OPTS="$CATALINA_OPTS -Xmx1024m"

Then you have to restart tomcat server. Then we can remotely connect the application running in remote system by using the IP and PORT specified above. 

Since JConsole is quite simple, it is used to find out if there are any performance issues in the application. It is the first step for performance monitoring. Normally we run JConsole for a couple of days, and study the performance graph. From the graph, we can speculate whether there are any performance issues or not. If we know that there are performance issues, then the next step is to go for more advanced monitoring tool which is capable of finding specific object or specific thread causing the performance issues. For example, if the application is spawning a lot of threads and creating CPU overhead, then we have to find out which specific threads are creating such problem, or  a lot memory is consume by objects and Garbage collector is not successful to release the memory, then we have to find out which specific object is causing such a memory leak.

2)  JVisualVM

This is more advanced tool and this is built-in with latest Java. It includes all functionality provided by JConsole, apart from that we can create thread dump, heap dump and application snapshot. The dump files can be analysed later using some other dump analyzer tools to get more performance monitoring. The dump analyzer tools such as JProfiler, YourKit are very nice commercial tools(you can have around 10 days of trial use). I feel really excited if we can find some free analyzer, then we should not bother about paying and licencing.


For remote connection, as mentioned in JConsole, we have to enable JMX in JVM.

3) Automation Approach

Yes, we can dump heap memory as a file, if we want to test it for whole night, but nobody stays in front of computer dumping memory.. lol. So, we should have mechanism that we can dump heap memory in regular interval, so that we can figure out which object is getting bloated with time; also can track the number of threads, and their characteristics.

There is a command line tool jmap which dumps the heap memory. Jmap needs process id to work, so we find out pid of the application from the list of java application using "jps" command from terminal.

#Find id of java applicaiton
jps 
#dump
jmap -dump:format=b,file=FILE_NAME PROCESS_ID


    This is complete script that can dump heap memory in regular intervals until specified dump files are     obtained.
 #!/bin/bash
#file:heapdump.sh
if [ $# -eq 0 ]; then
    echo >&2 "Usage: heapsump.sh  [ [  [  ] ] ]" 
    echo >&2 "    Defaults: run_user=root, count = 10, delay = 0.5 (seconds)" 
    exit 1
fi
pid=$1                  # required
user=${2:-root}         # defaults to root
count=${3:-10}          # defaults to 10 times
delay=${4:-0.5}         # defaults to 0.5 seconds
while [ $count -gt 0 ]
do
    sudo -u $user jmap -dump:format=b,file=dump.$pid.$(date +%Y%m%d%H%M%S.%N) $pid
    sleep $delay
    count=$(( $count-1 ))    
done
     Call this script this way: 
sh heapdump.sh PID [root [15 [10]]]
     All arguments are optional except PID.   Other parameters are user, count and interval(delay for next       dump).

4) Eclipse Memory Analyzer

  Till writing this text, I found Eclipse Memory Analyzer plugin which can be installed using
  http://download.eclipse.org/mat/1.4/update-site/

After installing this, we open memory analyzer perspective where we can dump heap memory from locally running VM. Not only this, you can open previously saved dump files and analyze. So, this is a great plugin, really great because it is free! I have to explore more to write more. So, later I will try more interesting features provided by this plugin. 

I could not perform online analyzing using Eclipse Memory Analyzer. However, this is possible using JProfiler. I guess Eclipse Memory Analyzer is sufficient for fully analysis of heap dumps. Again, JProfiler sucks when the heap size is huge(around a couple of gigs).