This is the sixth article in the series of articles exploring the tools and techniques for analyzing, monitoring, and improving the performance of Java applications.
The Art of Java Application Performance Analysis and Tuning-Part 1 The Art of Java Application Performance Analysis and Tuning-Part 2 The Art of Java Application Performance Analysis and Tuning-Part 3 The Art of Java Application Performance Analysis and Tuning-Part 4 The Art of Java Application Performance Analysis and Tuning-Part 5
The Art of Java Application Performance Analysis and Tuning-Part 7
In this blog we are going to discuss Java application tuning techniques.
Java Application performance tuning
Java Application performance tuning involves the tuning of following components.
- JVM Tuning
- OS/Hardware Tuning
- Database (MySQL/Oracle) Tuning
- Application (Code) Tuning
In this article we will discuss about Application (Code) Tuning.
Application (Code) Tuning
In my experience I came across the following techniques to improve the performance.
- Identify the bottlenecks and solve them
- Using Better Logic/Algorithms
- Using Less and Efficient DB Queries
- Caching
- Using Java Concurrency API for Improving Performance
How to identify Bottlenecks?
Using Thread dump Analysis: : Take multiple thread dumps during busy/peak hour. Analyze the thread dumps to identify the hot methods/frequently called methods and start optimizing the code/logic..
Using Method Profiling: : Use some profiler/ IBM Health Center – Profile option to find out the hot methods/frequently called methods and start optimizing the code/logic.
Using Application Logs: : Use the application logs/time stamps to measure the performance/response time and start optimizing the code/logic
Using Memory Analysis: : Use the Jmap/IBM Health Center – Classes option to find out the the high memory usage/OutOfMemory errors
Repeat above techniques until you meet your performance requirements.
Using Better Logic/Algorithms/Implementation
After identifying the bottlenecks we may need to optimize/change the code/logic.
single thread bottlenecks: Common reason for slowness/low throughput are single threaded bottlenecks. Single threaded bottlenecks are the code portions where only a single thread exists for processing. These bottlenecks cause other threads/data to wait every time they execute. Often these bottlenecks are the reason for high memory usage and OutOfMemory problems.
Notes:
- Design concurrent applications around execution of independent tasks (Java Concurrency Executor API).
- We can write faster algorithms by using Java Concurrency API/Parallel algorithms.
Using Less and Efficient DB Queries
Most of the Java applications are data-base bound. Even if you can scale-out your application, you can not scale the RDBMS data-bases easily. Efficient database modeling and query mechanisms are key to the data-base performance.
Notes:
1. It is difficult to change the Database model after project deployment. So we need to make the DB model right first time.
2. Use Batch Queries (PreparedStatement.addBatch, Hibernate Bulk addition, etc.) where-ever possible. In some cases batch queries are 100 times faster! than serial queries.
3. Always try to query on a indexed columns.
4. Care should be taken while doing JOIN queries on huge tables.
5. Some times queries need be tuned for specific DBs (Oracle , MySQL). Use EXPLAIN PLAN command to find out the cost of the query.
6. Care should be taken while using ORMs like Hibernate, JPA etc. Understanding ORM Query generation helps query tuning.
7. Poor database deployments/sizing can hurt the application performance severely. So monitor the DB (Oracle, MySQL) applications and tune the DB Server accordingly.
Excessive load on database effects the DB performance. “Caching” can be used to decrease the load on database.
Caching
The current mantra of industry for high performance and scalable applications are
- Scale horizontally (multiple/distributed servers)
- Cache as much as you can. The more useful cache the better the responsiveness.
Notes:
1. Cache frequently used data and static data.
2. Cache precomputed results for repeated use.
3. Use thread dump analysis/method profiling to identify the hot methods and try to cache the data.
4. Make sure your caches are configurable. So that caches can be tuned for project requirements.
5. Make sure your cache configurations are align with available RAM.
Using Java Concurrency API for Performance
The number of cores in multi-core processors has increased. Based on project requirements/network size we can add more and more processor-cores (scale up) to the hardware.
But the question is, Are we using the multi-core processors efficiently?
To keep all processor cores busy we need to code more fine grained and more scalable parallelism. The applications that have not been tuned for multi-core systems may suffer from performance problems.
In using Java Concurrency API to achieve better performance, we are trying to utilize the multi-core processing resources we have more effectively.
- Design concurrent applications around execution of independent tasks (Java Concurrency Executor API).
- We can write faster algorithms by using Java Concurrency API/Parallel algorithms.
Must read book for all Java developers : “Java Concurrency In Practice” by Brian Goetz”
Reference:
http://www.cs.hut.fi/u/tlilja/multicore/slides/java_multicore.pdf
http://highscalability.com/learn-how-exploit-multiple-cores-better-performance-and-scalability
More details on this topic in future article.