# Java Performance Tuning
# Reducing amount of Strings
In Java, it's too "easy" to create many String instances which are not needed. That and other reasons might cause your program to have lots of Strings that the GC is busy cleaning up.
Some ways you might be creating String instances:
myString += "foo";
Or worse, in a loop or recursion:
for (int i = 0; i < N; i++) {
myString += "foo" + i;
}
The problem is that each +
creates a new String (usually, since new compilers optimize some cases). A possible optimization can be made using StringBuilder
or StringBuffer
:
StringBuffer sb = new StringBuffer(myString);
for (int i = 0; i < N; i++) {
sb.append("foo").append(i);
}
myString = sb.toString();
If you build long Strings often (SQLs for example), use a String building API.
Other things to consider:
- Reduce usage of
replace
,substring
etc. - Avoid
String.toArray()
, especially in frequently accessed code. - Log prints which are destined to be filtered (due to log level for example) should not be generated (log level should be checked in advance).
- Use libraries like this (opens new window) if necessary.
- StringBuilder is better if the variable is used in a non-shared manner (across threads).
# An evidence-based approach to Java performance tuning
Donald Knuth is often quoted as saying this:
"Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%."
Bearing that sage advice in mind, here is the recommended procedure for optimizing programs:
-
1. If Yes, then return to step 4.
1. If No, then abandon the change and return to step 9. If you are making no progress, pick a different hotspot for your attention.
Eventually you will get to a point where the application is either fast enough, or you have considered all of the significant hotspots. At this point you need to stop this approach. If a section of code is consuming (say) 1% of the overall time, then even a 50% improvement is only going to make the application 0.5% faster overall.
Clearly, there is a point beyond which hotspot optimization is a waste of effort. If you get to that point, you need to take a more radical approach. For example:
- Look at the algorithmic complexity of your core algorithms.
- If the application is spending a lot of time garbage collection, look for ways to reduce the rate of object creation.
- If key parts of the application are CPU intensive and single-threaded, look for opportunities for parallelism.
- If the application is already multi-threaded, look for concurrency bottlenecks.
But wherever possible, rely on tools and measurement rather than instinct to direct your optimization effort.
# General approach
The internet is packed with tips for performance improvement of Java programs. Perhaps the number one tip is awareness. That means:
- Identify possible performance problems and bottlenecks.
- Use analyzing and testing tools.
- Know good practices and bad practices.
The first point should be done during the design stage if speaking about a new system or module. If speaking about legacy code, analyzing and testing tools come into the picture. The most basic tool for analyzing your JVM performance is JVisualVM, which is included in the JDK.
The third point is mostly about experience and extensive research, and of course raw tips that will show up on this page and others, like this (opens new window).