HDDS-9377. Replace MutableStat with lock-free ConcurrentMutableStat in OMLockMetrics and PerformanceMetrics - #11085
Open
yandrey321 wants to merge 3 commits into
Open
HDDS-9377. Replace MutableStat with lock-free ConcurrentMutableStat in OMLockMetrics and PerformanceMetrics#11085yandrey321 wants to merge 3 commits into
yandrey321 wants to merge 3 commits into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes were proposed in this pull request?
Problem
MutableStat.add(long) is synchronized. OMLockMetrics records four timing stats (read/write lock held and wait times) on every lock acquire and release. Under high read-lock concurrency — when many OM handler threads release a read-lock simultaneously and all rush to call add() — every thread serialises through the same mutex. This creates a thundering-herd contention point that limits OM throughput as thread counts grow.
Approach
Introduce ConcurrentMutableStat, a drop-in subclass of MutableStat that makes add() non-blocking:
Each call accumulates in LongAdder (sum, count) and LongAccumulator (min, max) — all cell-striped via Striped64, so threads write to independent cells with no cross-thread synchronisation.
setChanged() is deferred out of the hot-path add() to avoid concurrent volatile writes from all calling threads.
Pending cells are drained into the parent's running state lazily, only on snapshot(), lastStat(), or toString() — paths that already hold or take the stat's own lock and are called far less frequently than add().
OMLockMetrics and PerformanceMetrics are updated to use ConcurrentMutableStat for their stat fields.
Co-authored with Claude Opus 4.8
What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-9377
How was this patch tested?
Unit tests (TestConcurrentMutableStat): single-threaded count/mean/min/max correctness, multi-threaded count and extreme-value accuracy, multiple drain cycles.
Integration tests: TestFreon (OmBucketReadWriteFileOps, OmBucketReadWriteKeyOps) — both pass; verifyOMLockMetrics asserts sample counts > 0 for all four lock stats through the full cluster lock/unlock path.
Benchmark
x86
ARM64