Performance
GC: multiple-choice review
Six questions that cut across the whole unit. Each one mirrors a decision you make in a real incident — not a definition to recite, but a tradeoff to weigh under load.
Confirm you can connect allocation pressure, collector choice, tuning knobs, and production failure modes — the synthesis the individual lessons built toward.
Service A holds a 4 GB cache and allocates 50 MB/s. Service B holds 100 MB live and allocates 1 GB/s. Both run the same collector. Which sees more GC-driven tail latency, and why?
A Go service in a 4 GB container OOM-kills sporadically under traffic spikes; GOGC is the default 100. What is the first knob, and what does it actually do?
After migrating from G1 to (non-generational) ZGC, pauses drop from 60 ms to under 1 ms, but throughput falls ~12% and RSS rises ~18%. How do you read this?
Why does a concurrent collector need a write barrier, and what breaks without one?
A Java service that registers Object.finalize() on file-handle wrappers shows open-handle counts spiking unpredictably under load. Root cause?
gctrace shows GC CPU climbing 1% → 39% over an hour while concurrent-mark time grows from 1.3 ms to ~350 ms. What is happening and what is the first fix?
Across the unit the through-line is one decision tree: allocation rate sets GC frequency, the live set sets cycle cost, the collector sets pause shape, and the knobs (GOMEMLIMIT first, GOGC/pause-target second, algorithm last) defend the bounds. Production failures — OOM under spikes, ZGC tradeoffs, finalizer storms, death-spirals, allocation DoS — all resolve back to the same lever: reduce allocations before you tune anything.