title: Measure performance of Java application
body: <p>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)</p>
  
  <p>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. </p>
  
  <p>To determine execution time I have created a class with one threadlocal variable which contains logging statements, below is the code: </p>
  
  <pre><code>public class ExecutionTraceManager {
  
  private static Category cat = Category.getInstance(ExecutionTraceManager.class.getCanonicalName());
  
  private static final ThreadLocal&lt;Tracer&gt; traceContainer = new ThreadLocal&lt;Tracer&gt;() {
      @Override
      protected Tracer initialValue() {
          return new ExecutionTraceManager().new Tracer();
      }
  };
  
  public static void addTrace(String trace) {
      traceContainer.get().addTrace(trace);
  }
  
  public static void printTrace(){
      ArrayList&lt;String&gt; trace = traceContainer.get().trace;
      StringBuffer buffer = new StringBuffer();
      for(String current : trace){
          buffer.append(current).append("\n");
      }
  
      cat.info(buffer);
  }
  
  public class Tracer {
      ArrayList&lt;String&gt; trace = new ArrayList&lt;String&gt;();
      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());
      }
  }
  </code></pre>
  
  <p>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. </p>
  
  <p>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.</p>