An evidence-based approach to Java performance tuning
suggest changeDonald 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:
- First of all, design and code your program or library with a focus on simplicity and correctness. To start with, don’t spend much effort on performance.
- Get it to a working state, and (ideally) develop unit tests for the key parts of the codebase.
- Develop an application level performance benchmark. The benchmark should cover the performance critical aspects of your application, and should perform a range of tasks that are typical of how the application will be used in production.
- Measure the performance.
- Compare the measured performance against your criteria for how fast the application needs to be. (Avoid unrealistic, unattainable or unquantifiable criteria such as “as fast as possible”.)
- If you have met the criteria, STOP. You job is done. (Any further effort is probably a waste of time.)
- Profile the application while it is running your performance benchmark.
- Examine the profiling results and pick the biggest (unoptimized) “performance hotspots”; i.e. sections of the code where the application seems to be spending the most time.
- Analyse the hotspot code section to try to understand why it is a bottleneck, and think of a way to make it faster.
- Implement that as a proposed code change, test and debug.
- Rerun the benchmark to see if the code change has improved the performance:
- If Yes, then return to step 4.
- 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.
Found a mistake? Have a question or improvement idea?
Let me know.
Performance Tuning:
*
An evidence-based approach to Java performance tuning
Table Of Contents
2
Streams
6
Generics
7
File I/O
8
Arrays
10
Maps
11
Strings
17
Console I/O
18
Singletons
21
Autoboxing
25
JAXB
27
Networking
28
Optional
29
Enums
31
Annotations
32
Audio
33
Data Class
39
Operators
40
Asserting
41
Scanner
43
Preferences
45
Constructors
46
ByteBuffer
48
JSON in Java
50
Recursion
51
Polymorphism
55
Java Agents
58
BigInteger
59
BigDecimal
62
ThreadLocal
63
Logging
68
JVM Flags
75
Lists
77
LocalTime
78
Sets
89
JAX-WS
91
Performance Tuning
96
XJC
98
Process
101
Fluent Interface
106
Modules
109
ServiceLoader
110
ClasssLoader
114
Applets
115
NIO Networking
116
New File I/O
117
Secure objects
121
SecurityManager
122
JNDI
123
super keyword
126
Atomic types
129
sun.misc.Unsafe
131
Java deployment
134
Runtime commands
135
NumberFormat
138
Unit Testing
139
JavaBean
140
Expressions
141
Literals
144
Packages
150
JMX
153
JShell
154
Benchmarks
159
Sockets
160
Java Sockets
163
List vs. set
164
2D graphics
165
Reflection
166
Deque interface
167
Enum Map
168
EnumSet class
171
Immutable class
172
String Tokenizer
175
Hashtable
177
SortedMap
178
WeakHashMap
179
LinkedHashMap
180
StringBuffer
182
C++ Comparison
184
Contributors