# Why You Should Tune Code Before Your Garbage Collector

DevFeed: [Why You Should Tune Code Before Your Garbage Collector](<https://devfeed.tech/articles/why-you-should-tune-code-before-your-garbage-collector-30761.md>)

Original publisher: [Read original article](<http://blog.vanillajava.blog/2026/06/why-you-should-tun-code-before-your.html>)

Author: Peter Lawrey (noreply@blogger.com)

Published: 2026-06-08T11:52:44Z

Content type: article

Language: en

Sources: [Vanilla Java](<https://devfeed.tech/sources/vanilla-java.md>)

Topics: [Benchmark](<https://devfeed.tech/topics/benchmark.md>), [Java](<https://devfeed.tech/topics/java.md>), [Latency](<https://devfeed.tech/topics/latency.md>), [Logging](<https://devfeed.tech/topics/logging.md>), [Code](<https://devfeed.tech/topics/code.md>)

Tags: [benchmark](<https://devfeed.tech/tags/benchmark.md>), [benchmarks](<https://devfeed.tech/tags/benchmarks.md>), [io](<https://devfeed.tech/tags/io.md>), [java](<https://devfeed.tech/tags/java.md>), [latency](<https://devfeed.tech/tags/latency.md>), [logging](<https://devfeed.tech/tags/logging.md>), [low-latency](<https://devfeed.tech/tags/low-latency.md>), [performance](<https://devfeed.tech/tags/performance.md>)

## AI overview

A Java latency benchmark compares garbage collectors while varying redundant SLF4J logging and log storage. The article reports that removing redundant logging can have a much larger effect on extreme tail latency than changing the garbage collector, and can change which collector performs best.

## Source excerpt

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. In this post I look at a simple event to response latency benchmark, MarketDataSnapshot to NewOrderSingle at 50K/s for 30 minutes using JLBH to test Chronicle-FIX. The goal is to compare a system which is doing redundant work (in this case logging each message using SLF4J), compared with not logging (Chronicle-FIX records every message internally using Chronicle Queue) and how this changes the choice of Garbage Collector For the p99 (worst 1 in 100) the choice of Garbage Collector makes a different on par with optimising how loggin is done However, for the p99.99 (worst 1 in 10,000) optimsing how the logging is done is orders of magnitude more signifciant than the choice of Garbage Collector Unoptimised Benchmark This takes the optimised benchmark and adds one SLF4J log line of just the message to be sent. One log line might not sound like much but ding this on every message makes a big difference esp when the rest of the code is written for low latency. Table 1. RTT latency distribution with slf4j logging GC option p99 p99.99 Parallel large Eden, no large pages 16.86 20,480 ZGC, no large pages 12.21 19,694 G1 + COH, no large pages 12.02 20,349 G1, 2 MiB large pages 13.94 20,021 Shenandoah generational, no large pages 12.30 19,235 Note The p99.99 are thousands of microseconds or 19 to 20 milliseconds. The p99.99 or worst 1 in 10,000 might sound rare, however at 50K/s that is 5 times per second or 300 times per minute Based on these results, you might conclude that Shenandoah is a good option, and avoid Parallel GC. How much difference is the disk IO making IO is often a significant proportion of delays, and we can see that just moving where the logs are written. In this case to a tmpfs filesystem. Table 2. RTT latency distribution with slf4j logging to /dev/shm GC option p99 p99.99 Parallel large Ede