HDDS-16288. Replace MutableRate with lock-free ConcurrentMutableRate on OM hot-path metrics - #11128
Open
yandrey321 wants to merge 1 commit into
Open
HDDS-16288. Replace MutableRate with lock-free ConcurrentMutableRate on OM hot-path metrics#11128yandrey321 wants to merge 1 commit into
yandrey321 wants to merge 1 commit 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
OM request-latency metrics are recorded as Hadoop
@MetricMutableRate counters. MutableRate extends MutableStat, and MutableStat.add(long) is synchronized(this). On the OM hot path many handler threads record a measurement on the same metric instance, so they serialize on that per-counter monitor — a lock convoy that appears under concurrent load. A single getKeyInfo touches 6–7 of these counters in sequence, so the effect compounds on the read path.HDDS-9377 (already merged) introduced the lock-free ConcurrentMutableStat (striped LongAdder/LongAccumulator, drained lazily at snapshot) and applied it to OMLockMetrics and the PerformanceMetrics wrapper. The remaining MutableRate counters in OMPerformanceMetrics and KeyLifecycleServiceMetrics are the gap this PR closes, scoped deliberately to OM hot-path classes only.
Approach
New ConcurrentMutableRate (hadoop-hdds/common) — a lock-free counterpart of Hadoop's MutableRate, extending ConcurrentMutableStat with a public constructor that fixes sampleName="Ops" / valueName="Time". Hadoop's MutableRate constructor is package-private and only instantiable reflectively by the
@Metricfactory; this public ctor lets OM metric sources build it directly. Semantics and emitted names (NumOps / AvgTime) are identical.OMPerformanceMetrics — converted all 44
@MetricMutableRate latency counters to ConcurrentMutableRate. Because@Metricfields are instantiated reflectively (the factory always builds a real MutableRate, so a field cannot simply be retyped), the class is reworked into a hand-rolled MetricsSource following the OMLockMetrics / S3GatewayMetrics template: stats built in the constructor, getMetrics() snapshots all 44 stats plus the 6 surviving@Metricgauges. The single-writer gauges (listKeysOpsPerSec + 5 *ServiceLatencyMs) stay@Metric.KeyLifecycleServiceMetrics — taskLatencyMs (written concurrently by the lifecycle BackgroundService pool, per bucket) converted to ConcurrentMutableRate; the class becomes a hand-rolled MetricsSource. Its 13 MutableGaugeLong gauges remain
@Metric.MetricUtil.captureLatencyNs — the two overload parameters widened from MutableRate to its superclass MutableStat. The body already only calls add(long). This is source-compatible (MutableRate and ConcurrentMutableStat both extend MutableStat) and lets all existing captureLatencyNs(getter(), block) call sites in ozone-manager compile unchanged.
Metric-name compatibility
All emitted metric names are preserved byte-identically: the capitalized field name plus extended=false reproduces exactly the NumOps / AvgTime pairs the
@Metricfactory generated. No dashboard or alert names change. Caveat: standard deviation is slightly underestimated under concurrent batched adds (documented on ConcurrentMutableStat, inherited here) — acceptable for these latency stats.Not converted (deliberately)
OzoneManagerDoubleBufferMetrics (flushTime, queueSize) — written only by the single OMDoubleBufferFlushThread daemon, so there is no cross-thread contention and lock-free would only add churn. The MutableGaugeLong/Float gauges throughout are single-writer and left as
@Metric.The genuinely-contended per-RPC MutableRate counters in the shared ipc_ fork (RpcMetrics) are out of OM scope and tracked separately (HDDS-16304).
Generated-by: Claude Code (Opus 4.8)
What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-16288
How was this patch tested?
CI: https://github.com/yandrey321/ozone/actions/runs/33043941610/job/98425998600
Unit tests
Integration tests