Why You Should Tune Code Before Your Garbage Collector
Tune Code Before Your Garbage Collector

I tested how redundant logging impacts latency compared to choosing different Java Garbage Collectors like ZGC and Shenandoah. My benchmarks reveal that optimizing code to remove unnecessary work often matters far more than tuning the Garbage Collector, sometimes even flipping which collector performs best for your specific workload.
"Optimising your memory allocations in Java could make far more difference than your choice of Garbage Collector and may even change which is the best garbage collector."
HN discussion
- Manual allocation tuning is often a temporary necessity that reverses itself as the JVM Hotspot compiler improves, sometimes even outperforming native code optimizations.
- Primitive boxing in hot paths creates disproportionate GC pressure that the JVM cannot always eliminate automatically, necessitating manual intervention.
- Caching immutable objects like LocalDate or Integers can significantly reduce memory footprint and GC load, though this is a workaround until Project Valhalla introduces value types.
- Logging calls that construct strings or LogEvent objects before checking log levels can cause unnecessary OldGen promotion and trigger expensive major collections.
- Allocation discipline expectations vary drastically by domain, with high-performance systems like MPP databases enforcing strict avoidance of allocations unlike general cloud application development.