Bound native NIO buffer retention after large socket writes - #2929
Conversation
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 WalkthroughWalkthroughThe web service command sets an NIO cached-buffer limit and enables native-heap trimming once per minute with info-level logging. The infrastructure README documents these settings, observed memory measurements, monitoring, limits, and JVM option overrides. ChangesNative memory trimming
Priority: ⬆️ High Estimated code review effort: 2 (Simple) | ~8 minutes Change: Bug fix Merge Risk: ⚪ Minimal · up to The production runtime accepts the new memory settings, and the documented override order is preserved. No unresolved change-specific risk remains; the change is ready to merge subject to normal checks. Architecture SummaryArchitecture risk: 🔵 Low · up to The change affects 1 system. Changed systems: Architecture concerns Review detailsSystems and components
Before / after behavior
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Large WebSocket writes leave native NIO copy buffers cached on long-lived IO threads. Corretto 26 does not limit their cached size by default, and these buffers are excluded from both the direct-buffer MXBean and
MaxDirectMemorySize. This fixes a confirmed source of native growth implicated in the September 28 host-memory outages.Set
jdk.nio.maxCachedBufferSize=131072so temporary buffers larger than 128 KiB are freed after I/O. Ordinary Java socket buffers remain reusable and large messages remain supported. Also enable native heap trimming every 60 seconds to return freed glibc pages. Both defaults precedeJAVA_OPTSfor explicit overrides; the operational notes describe rollback and rollout checks.Evidence:
Util.getTemporaryDirectBuffer → SocketChannelImpl.write → Undertow.flushSenders. It maps to the exact repeated 36,237,312-byte resident growth unit observed independently.Validation on the exact cached Linux Corretto 26 runtime:
JAVA_OPTSheap options, and accepts both rollback overrides.3a57848451595b0d438d6f391041092e6b897784.The cap applies per cached buffer, not to in-flight or all native memory. Backpressured large writes do more allocation/free work; local timing under emulation is not a production latency guarantee. The failed processes were unavailable for a cache census, so the evidence does not retrospectively account for every byte of their RSS. Observe memory and request/reactivity latency through large-message traffic and a complete backup cycle after rollout.
This PR is not deployed. Instance-count configuration is unchanged from main.