<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="10.0.0-rc.1.25451.107" />

Base2ExponentialHistogramAggregator

using System.Numerics; using System.Runtime.CompilerServices; namespace System.Diagnostics.Metrics { internal sealed class Base2ExponentialHistogramAggregator : Aggregator { private int _scale; private double _maxMeasurement; private double _minMeasurement; private double _sum; private long _count; private bool _reportDeltas; private double _scalingFactor; internal CircularBufferBuckets PositiveBuckets { get; } internal int Scale { get { return _scale; } set { _scale = value; _scalingFactor = BitConverter.Int64BitsToDouble(1993721221186302 | (1023 + (long)value << 52)); } } internal long ZeroCount { get; set; } public Base2ExponentialHistogramAggregator(int maxBuckets = 160, int scale = 20, bool reportDeltas = false) { if (scale < -11 || scale > 20) throw new ArgumentOutOfRangeException("scale", System.SR.Format(System.SR.InvalidHistogramScale, scale, -11, 20)); if (maxBuckets < 2) throw new ArgumentOutOfRangeException("maxBuckets", System.SR.Format(System.SR.InvalidHistogramMaxBuckets, maxBuckets, 2)); Scale = scale; _reportDeltas = reportDeltas; _minMeasurement = 1.7976931348623157E+308; _maxMeasurement = -1.7976931348623157E+308; PositiveBuckets = new CircularBufferBuckets(maxBuckets); } public override IAggregationStatistics Collect() { lock (this) { Base2ExponentialHistogramStatistics result = new Base2ExponentialHistogramStatistics(Scale, ZeroCount, _sum, _count, _minMeasurement, _maxMeasurement, PositiveBuckets.ToArray()); if (_reportDeltas) { _sum = 0; _minMeasurement = 1.7976931348623157E+308; _maxMeasurement = -1.7976931348623157E+308; ZeroCount = 0; _count = 0; PositiveBuckets.Clear(); } return result; } } public override void Update(double measurement) { if (IsFinite(measurement)) { int num = measurement.CompareTo(0); if (num >= 0) { lock (this) { _maxMeasurement = Math.Max(_maxMeasurement, measurement); _minMeasurement = Math.Min(_minMeasurement, measurement); _count++; if (num == 0) ZeroCount++; else { _sum += measurement; int num2 = MapToIndex(measurement); int num3 = PositiveBuckets.TryIncrement(num2, 1); if (num3 != 0) { PositiveBuckets.ScaleDown(num3); Scale -= num3; if (Scale < -11) Scale = -11; else if (Scale > 20) { Scale = 20; } num3 = PositiveBuckets.TryIncrement(num2 >> num3, 1); } } } } } } public int MapToIndex(double value) { long num = BitConverter.DoubleToInt64Bits(value); long num2 = num & 4503599627370495; if (Scale > 0) { if (num2 == 0) return ((int)((num & 9218868437227405312) >> 52) - 1023 << Scale) - 1; return (int)Math.Ceiling(Math.Log(value) * _scalingFactor) - 1; } int num3 = (int)((num & 9218868437227405312) >> 52); if (num3 == 0) num3 -= LeadingZero64(num2 - 1) - 12; else if (num2 == 0) { num3--; } return num3 - 1023 >> -Scale; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool IsFinite(double value) { return double.IsFinite(value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LeadingZero64(long value) { return BitOperations.LeadingZeroCount((ulong)value); } } }