Ashutosh Shukla
Ashutosh Shukla

Reputation: 11

Measure performance of Java application

I am working on an application which is at least 15 years old. I am working on improving the performance of a particular flow which has around 10K lines of code. This flow involves sending information to external systems on JMS topic. There were issues that I identified in the way we were creating and caching session after resolving those issues I have been able to save some time. Now I want to further improve the performance. For this, I need to go through an entire 10K line of code and determine where I have the scope of saving time. This flow is divided into three parts - Fist part creates batches of individual requests and performs some operations (Thread pool of size 15) Second part takes input from first part and do some more processing (thread pool of 10 threads) Third part takes input from second part and do some more processing (thread pool of 10 threads)

I can not increase the number of threads because resources are limited and this not the only flow in an application (my config is - 2 sockets, 12 core per socket and 2 threads per core). Also, I don't have much liberty to play with this because these first, second and third parts are used elsewhere also.

To determine execution time I have created a class with one threadlocal variable which contains logging statements, below is the code:

public class ExecutionTraceManager {

private static Category cat = Category.getInstance(ExecutionTraceManager.class.getCanonicalName());

private static final ThreadLocal<Tracer> traceContainer = new ThreadLocal<Tracer>() {
    @Override
    protected Tracer initialValue() {
        return new ExecutionTraceManager().new Tracer();
    }
};

public static void addTrace(String trace) {
    traceContainer.get().addTrace(trace);
}

public static void printTrace(){
    ArrayList<String> trace = traceContainer.get().trace;
    StringBuffer buffer = new StringBuffer();
    for(String current : trace){
        buffer.append(current).append("\n");
    }

    cat.info(buffer);
}

public class Tracer {
    ArrayList<String> trace = new ArrayList<String>();
    long startTime = System.nanoTime();
    boolean init = false;
    public void addTrace(String traceMessage) {
        if(!init){
            startTime = System.nanoTime();
            init = true;
        }
        StringBuffer buffer = new StringBuffer("Time taken till [ ")
                .append(traceMessage)
                .append(" ] is : "
                        + ((System.nanoTime() - startTime) / 1000000.0));
        trace.add(buffer.toString());
    }
}

In my code, i just call ExecutionTraceManager.addTrace and once the thread completes the task I call printTrace and also reset the thread local so that next time when this thread processes next request it sees empty trace list.

This is fine with me but I want to understand what are other ways of identifying which code is taking time (because I have ~10 line of code). what approach professionals take to handle such problems.

Upvotes: 1

Views: 1842

Answers (2)

abstractnature
abstractnature

Reputation: 456

Use a JProfiler, easy and simple to use.

Run the JAVA Program through it, to measure CPU usage of various functions,memory usage, garbage collection etc. https://www.ej-technologies.com/products/jprofiler/overview.html

Upvotes: 0

kewne
kewne

Reputation: 2298

Use a metrics collection library

Using a metrics collection library like Metrics is, in my opinion, a better solution than rolling your own because it deals with sampling and has various metric implementations (timer, histogram, etc). Essentially you add code like this:

private final Timer responses = metrics.timer(name(RequestHandler.class, "responses"));

// in the method
    try (Timer.Context ctx = responses.time()) {
        // run operations
    }
}

This produces a histogram of execution times that you can query for various percentiles (99, 95, 90, etc.). It also has the advantage that you can run it in your production systems and collect the metrics.

I prefer this approach over profilers because profilers tend to produce very dense output that is difficult to map to what your application does. Timing metrics at the application level produces metrics that are easier to understand and act upon.

Use a profiler

You can also use a profiler like the one in Mission Control's Flight Recorder, although running it in production environments requires a paid license. As was mentioned in other answers, there are other tools like VisualVM that have profilers you can use.

Upvotes: 2

Related Questions