Java Code Optimisation Techniques
performance - What are some best practices to build memory-efficient Java applications? - Stack Overflow
profiling - Java performance tips - Stack Overflow
Video: Secure Coding Guidelines for Java SE
Videos
I’m currently writing my dissertation on code optimisation techniques in Java. I’m currently doing my literature review and was wondering if anyone has good resources for code optimisations specifically (excluding JVM tuning).
Sorry if this is classed as learning and not appropriate.
I am looking at time and space complexity of different data structures, data types, JCF, class initialisation and so on.
Some techniques I use to reduce memory:
- Make your own IntArrayList (etc) class that prevents boxing
- Make your own IntHashMap (etc) class where keys are primitives
- Use nio's ByteBuffer to store large arrays of data efficiently (and in native memory, outside heap). It's like a byte array but contains methods to store/retrieve all primitive types from the buffer at any arbitrary offset (trade memory for speed)
- Don't use pooling because pools keep unused instances explicitly alive.
- Use threads scarcely, they're super memory hungry (in native memory, outside heap)
- When making substrings of big strings, and discarding the original, the substrings still refer to the original. So use
new Stringto dispose of the old big string. - A linear array is smaller than a multidimensional array, and if the size of all but the last dimension is a power of two, calculating indices is fastest:
array[x|y<<4]for a 16xN array. - Initialize collections and
StringBuilderwith an initial capacity chosen such that it prevents internal reallocation in a typical circumstance.- Use
StringBuilderinstead of string concatenation, because the compiled class files usenew StringBuilder()without initial capacity to concatenate strings.
- Use
Depends on the application, but generally speaking
Layout data structures in (parallel) arrays of primitives
Try to make big "flat" objects, inlining otherwise sensible sub-structures
Specialize collections of primitives
Reuse objects, use object pools, ThreadLocals
Go off-heap
I cannot say these practices are "best", because they, unfortunately, make you suffer, losing the point why you are using Java, reduce flexibility, supportability, reliability, testability and other "good" properties of the codebase.
But, they certainly allow to lower memory footprint and GC pressure.
do not try to outsmart the jvm.
in particular:
don't try to avoid object creation for the sake of performance
use immutable objects where applicable.
use the scope of your objects correctly, so that the GC can do its job.
use primitives where you mean primitives (e.g. non-nullable int compared to nullable Integer)
use the built-in algorithms and data structures
when handing concurrency use java.util.concurrent package.
correctness over performance. first get it right, then measure, then measure with a profiler then optimize.
Obviously, profile profile profile. For Eclipse there's TPTP. Here's an article on the TPTP plugin for Eclipse. Netbeans has its own profiler. jvisualvm is nice as a standalone tool. (The entire dev.java.net server seems to be down at the moment, but it is very much an active project.)
The first thing to do is use the library sorting routine, Collections.sort; this will require your data objects to be Comparable. This might be fast enough and will definitely provide a good baseline.
General tips:
- Avoid locks you don't need (your JVM may have already optimized these away)
- Use
StringBuilder(notStringBufferbecause of that lock thing I just mentioned) instead of concatenatingStringobjects - Make anything you can
final; if possible, make your classes completely immutable - If you aren't changing the value of a variable in a loop, try hoisting it out and see if it makes a difference (the JVM may have already done this for you)
- Try to work on an
ArrayList(or even an array) so the memory you're accessing is contiguous instead of potentially fragmented the way it might be with aLinkedList - Quicksort can be parallelized; consider doing that (see quicksort parallelization)
- Reduce the visibility and live time of your data as much as possible (but don't contort your algorithm to do it unless profiling shows it is a big win)