diff --git a/src/OpenTelemetry/Metrics/Base2ExponentialBucketHistogram.cs b/src/OpenTelemetry/Metrics/Base2ExponentialBucketHistogram.cs index 7ed40b4dc28..1d63d898443 100644 --- a/src/OpenTelemetry/Metrics/Base2ExponentialBucketHistogram.cs +++ b/src/OpenTelemetry/Metrics/Base2ExponentialBucketHistogram.cs @@ -23,8 +23,6 @@ internal sealed partial class Base2ExponentialBucketHistogram internal double RunningMax = double.NegativeInfinity; internal double SnapshotMax; - internal int IsCriticalSectionOccupied = 0; - internal ExponentialHistogramData SnapshotExponentialHistogramData = new(); private int scale; diff --git a/src/OpenTelemetry/Metrics/HistogramBuckets.cs b/src/OpenTelemetry/Metrics/HistogramBuckets.cs index b6e8d3ae632..6ef36eb6867 100644 --- a/src/OpenTelemetry/Metrics/HistogramBuckets.cs +++ b/src/OpenTelemetry/Metrics/HistogramBuckets.cs @@ -27,8 +27,6 @@ public class HistogramBuckets internal double RunningMax = double.NegativeInfinity; internal double SnapshotMax; - internal int IsCriticalSectionOccupied = 0; - private readonly BucketLookupNode? bucketLookupTreeRoot; private readonly Func findHistogramBucketIndex; diff --git a/src/OpenTelemetry/Metrics/MetricPoint.cs b/src/OpenTelemetry/Metrics/MetricPoint.cs index aedf5cf3c5d..306a14bf853 100644 --- a/src/OpenTelemetry/Metrics/MetricPoint.cs +++ b/src/OpenTelemetry/Metrics/MetricPoint.cs @@ -455,7 +455,7 @@ internal void UpdateWithExemplar(long number, ReadOnlySpan> tags = default, bool reportExemplar = false, bool isSampled = false) { Debug.Assert(this.mpComponents?.HistogramBuckets != null, "HistogramBuckets was null"); - var histogramBuckets = this.mpComponents!.HistogramBuckets; + var histogramBuckets = this.mpComponents!.HistogramBuckets!; - AcquireLock(ref histogramBuckets!.IsCriticalSectionOccupied); + this.mpComponents.AcquireLock(); unchecked { @@ -1354,16 +1341,16 @@ private void UpdateHistogram(double number, ReadOnlySpan> tags = default, bool reportExemplar = false, bool isSampled = false) { Debug.Assert(this.mpComponents?.HistogramBuckets != null, "HistogramBuckets was null"); - var histogramBuckets = this.mpComponents!.HistogramBuckets; + var histogramBuckets = this.mpComponents!.HistogramBuckets!; - AcquireLock(ref histogramBuckets!.IsCriticalSectionOccupied); + this.mpComponents.AcquireLock(); unchecked { @@ -1382,7 +1369,7 @@ private void UpdateHistogramWithMinMax(double number, ReadOnlySpan> tags = default, bool reportExemplar = false, bool isSampled = false) @@ -1393,7 +1380,7 @@ private void UpdateHistogramWithBuckets(double number, ReadOnlySpan> tags = default, bool reportExemplar = false, bool isSampled = false) @@ -1422,7 +1409,7 @@ private void UpdateHistogramWithBucketsAndMinMax(double number, ReadOnlySpan @@ -20,9 +22,9 @@ internal sealed class MetricPointOptionalComponents public Exemplar[]? Exemplars; - public int IsCriticalSectionOccupied = 0; + private int isCriticalSectionOccupied = 0; - internal MetricPointOptionalComponents Copy() + public MetricPointOptionalComponents Copy() { MetricPointOptionalComponents copy = new MetricPointOptionalComponents { @@ -38,4 +40,32 @@ internal MetricPointOptionalComponents Copy() return copy; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void AcquireLock() + { + if (Interlocked.Exchange(ref this.isCriticalSectionOccupied, 1) != 0) + { + this.AcquireLockRare(); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ReleaseLock() + { + Interlocked.Exchange(ref this.isCriticalSectionOccupied, 0); + } + + // Note: This method is marked as NoInlining because the whole point of it + // is to avoid the initialization of SpinWait unless it is needed. + [MethodImpl(MethodImplOptions.NoInlining)] + private void AcquireLockRare() + { + var sw = default(SpinWait); + do + { + sw.SpinOnce(); + } + while (Interlocked.Exchange(ref this.isCriticalSectionOccupied, 1) != 0); + } }