Performance & Optimization
Performance Methodology
- Quantify first: throughput, latency percentiles (p99, not mean), footprint, utilization
- Top-down: system → JVM (GC/JIT) → code — most wins live above the code level
- Change one variable per experiment; keep everything else fixed
- Averages lie: latency is a distribution with a long tail; report percentiles
- Optimize judiciously (EJ 67): write good programs, measure, then optimize the proven hot 3%
- Beware the classic antipatterns: shiny tuning flags, folklore recipes, benchmarking the wrong thing
Optimizing Java opens with the uncomfortable truth: most "performance work" in industry is guessing. The antidote is a measurement loop — establish a baseline on production-like hardware and data, state a hypothesis ("GC pauses cause the p99 spikes"), test it with the right tool (GC logs, profiler, JFR), apply one change, and re-measure. If you cannot say what number you are trying to move and by how much, you are not optimizing yet.
| Metric | Definition | Watch out |
|---|---|---|
| Throughput | work units / time (req/s) | meaningless without a latency bound |
| Latency | time per operation, as a distribution | p50 hides the tail your users feel |
| Utilization | % of capacity in use | 100% CPU ≠ useful work (GC? spinning?) |
| Footprint | memory/CPU required | the cloud bill dimension |
| Saturation point | load where latency departs linearity | find it before production does |
Antipatterns catalog (Optimizing Java ch. 4, OCNJ appendix B): Shiny tuning — cargo-culted JVM flags from old blogs; Fiddle with switches — tuning before diagnosing; Performance tuning wizardry — trusting the lone hero over the measurement; Missing the bigger picture — micro-optimizing code while the database does table scans; UAT-is-my-desktop — testing on hardware unlike production. Each is a social failure as much as a technical one.