Improve Performance of Java Based Application

Improve Performance of Java Based Application

Motivation

  • In my project, I am part of the scalibility initative, where we wants to scale our system for 3Million users, or you can say 3Million users under one users,
  • Yes, as any other system, there are so many issues with the system , when any particular system scales, so we will look how to tackle this problem, and bring the best user experience.
  • Whatever we will discuss will apply to most of the other systems out there, you can just mix and match and you these kind of steps in your application to see the performance bump.

Non functional requirements for performance

  1. Availability
  2. Scalability
  3. performance

  4. Average application response time

  5. Average concurrent users the system must support
  6. Expected requests per second during peak load

How to identify Bottlenecks

  • lets say we have an application, we will run the load tests and on side we will run the APM , Application Performance Management to measure the CPU,Heap Usage, IO etc.
  • once we found the bottlenecks and the areas that can be improved, we have the list of API calls that are taking more time, or the Page load time is higher, we will document it at one place, and pick the pages which are the most used by our customer.

1. Optimizing the Performance by Good Coding practices.

  1. Avoid Getting the Size of the Collection in the Loop
  2. if we find the size in the loop we will be finding the size again and again and that is the issue.
List<String> objList = getData();
for (int i = 0; i < objList.size(); i++) { execute code ..}
  • optimised way
List<String> objList = getData();
int size = objList.size();    
for (int i = 0; i < size; i++) { execute code ..}
  1. For concatenation use StringBuffer or StringBuilder
  2. since when we concatenate new string is created in string pool constant that is part of heap memory. I will also link my older blogpost on string and Immutable class you can go through that to improve your understanding.
//not optimized
public String stringAppendLoop() {
    String s = "";
    for (int i = 0; i < 10000; i++) {
        if (s.length() > 0)
            s += ", ";
        s += "bar";
    }
    return s;
}

//optimized --> since we are not creating new string everytime saving heap memory :) 
public String stringAppendBuilderLoop() {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 10000; i++) {
        if (sb.length() > 0)
            sb.append(", ");
        sb.append("bar");
    }
    return sb.toString();
}
  1. Avoid Recursion ,
  2. it can lead to StackOverflowError

  3. Use Regular Expression Carefully.

  4. regular expression can take a toll on your application, since it is computational heavy
  5. You can cache the regular expression, instead of doing it again and again.
  6. String function in java such as String.replaceAll() and String.split(), these functions uses string.
  7. Parallel Processing.

  8. we can use executor service with thread pool to run parallel tasks
  9. Fork/Join Framework can help to run the parallel tasks using worker threads.
  1. Use primitive instead of objects --> pending --> read more on this
  2. primitive type is stored in stack, and stack is comparatively faster than heap, means use int over Integer and double or Double.

  3. Avoid creating big objects often

  4. objects such as db connection,configuration objects or session objects these objects contains a lot of information and creating them again and again will put load on the system since huge memory and resources will be consumed.
  5. Instead of creating some objects again and again use the single object.
  6. since the creation of big object will hamper the performance due to memory usage.
  7. Use singleton pattern and reuse the object or clone it
  • Yes , I am seeing this in case of updateInformation where one object creation is taking too much time to process.

  • Use SP instead of Queries

  • Use Prepared statement instead of Statement.

  • Use of Log Statements and levels

  • avoid logging big objects.

11.Select Required columns in a Query

  • while selecting the columns only select the columns needed.

  • Fetch Data using joins instead of subQuery

  • create index of columns that are freuqently used.

  • Use Profiler to check code performance

  • check code performance using profiler

14.Use Apache Commons StringUtils.replace instead of String.replace

  • In general, the String.replace method works fine and is pretty efficient, especially if you’re using Java 9.

  • But if your application requires a lot of replace operations and you haven’t updated to the newest Java version, it still makes sense to check for faster and more efficient alternatives.

  • One candidate is Apache Commons Lang’s StringUtils.replace method. As Lukas Eder described in one of his recent blog posts, it dramatically outperforms Java 8’s String.replace method.

  • And it just requires a minimal change. You need to add a Maven dependency for the Apache’s Commons Lang project to your application pom.xml, and replace all calls of the String.replace method with the StringUtils.replace method.

// replace this
test.replace(“test”, “simple test”);

// with this
StringUtils.replace(test, “test”, “simple test”);
  1. Caching Database Connections

2. JVM Tuning

  1. Heap Size Tuning.
  2. How many different applications we are planning to deploy to a single JVM process, e.g., the number of EAR files, WAR files, jar files, etc.?
  3. How many Java classes will be potentially loaded at runtime; including third party API’s?
  4. Estimate the footprint necessary for in-memory caching, e.g., internal cache data structures loaded by our application (and third party API’s) such as cached data from a database, data read from a file, etc.
  5. Estimate the number of Threads that the application will create.

The most reliable way to get a good idea about what the application needs are, is to run a realistic load test against the application and track metrics at runtime.

  1. Right Garbage Collector

3. JDBC Performance

  1. Connection Pooling
  2. since jdbc connections are expensive

  3. JDBC Batching

  4. Statement Caching

  5. Scale up and Scale out

  6. Database Scaling and Sharding

Architectural Improvements

  1. Caching
  2. Web frameworks such as Spring MVC can also leverage the built-in caching support in Spring, as well as the powerful HTTP-level caching based on ETags.
  3. or use redis or hazlecast as a standalone caching mechanism.