The hidden lock inside ArrayPool<byte>.Shared that cost 20% CPU
How live CPU profiling and BCL decompilation exposed a hidden monitor lock inside ArrayPool<byte>.Shared causing a 20% CPU regression.
A market-data-gateway service saw CPU climb roughly 20% after what looked like a pure win: swapping a custom byte-array cache for the BCL's ArrayPool<byte>.Shared. No analyzer flagged anything, because nothing in the diff looked wrong — the regression only existed at runtime, under a specific usage pattern.
A live CPU sample taken via dotnet-diagnostics-mcp showed 15.8% of samples sitting inside Monitor.Enter_Slowpath, despite the codebase containing zero explicit lock statements. Tracing the call tree back showed the contention originated inside the pool's own Rent/Return wrappers, not application logic.
Using dotnet-assembly-mcp, the team decompiled the actual SharedArrayPool<T> implementation shipped in the running .NET 10 build straight from System.Private.CoreLib. It revealed a per-core fallback path guarded by a plain Monitor.Enter/Exit, only hit when a thread's single-slot thread-local cache slot is unavailable — which happens whenever a different thread returns a buffer than the one that rented it. The application code did exactly that: one dedicated thread rented buffers, while N per-connection consumer tasks returned them.
The takeaway for engineers: ArrayPool<T>.Shared's thread-local fast path is silent and free, but cross-thread rent/return patterns bypass it entirely and fall back to a genuinely contended monitor — invisible to static analysis and only diagnosable by inspecting live runtime behavior and the actual compiled implementation.