Tuning Java applications for performance covers the following areas:
- technology: specific JVM details, garbage collector ...
- tooling: visualvm, vmstart, verbose gc ...
- methodology: identify goals, measure production data, benchmark ...
Java applications run on a dynamic environment. This is a huge advantage as the HotSpot compiler can adapt and optimize the runtime according to production-time measurements, usage scenarios and available hardware. Static languages like C and C++ don’t have that possibility and can only be optimized at compile time. With this dynamicity in mind, one investigating Java Performance must investigate the complete ‘box’, which consists of these layers:
- Actors: batch jobs, users, peak usage …
- Application: locks (locks are not always bad: they can preserve CPU), static code, libraries …
- JVM / OS: Sun JVM vs IBM, thread implementation …
- Hardware: memory, cpu, optimized instruction sets …
--> look for the dominant element of performance issues (=break down).
Some tools to investigate performance:
- OS: vmstat, mpstat, corestat …
- JVM: -verbosegc (even on production), gchisto, hpjmeter
- specific IBM “monitoring and diagnostic” tools (beta)
- java –xtrace: … for simple ‘entering/leaving method’ style logging, built in the jvm
- profilers (JProfiler is my favorite)
- loadtesting tools: JMeter and Grinder (read on)
Although standard Garbage Collectors run well out of the box, they often require optimizations and tuning once ‘real life’ applications run. When using “Generational collectors”, tuning is typically done with visualvm by modifying the eden, generational and old heap spaces at the JVM command line.
Load-testing Java applications:
- <> stress test: load tests an application using production-like load, while a stress test investigates the breaking point of an application.
- have a production-like setup
- gather relevant expected load figures
- avoid caches
- avoid ‘noise’ like irrelevant network overhead
- use mocks for external systems
- tools: e.g. JMeter