<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="10.0.0-preview.6.25358.103" />

Base2ExponentialHistogramAggregator

using System.Runtime.CompilerServices; namespace System.Diagnostics.Metrics { internal sealed class Base2ExponentialHistogramAggregator : Aggregator { private const int MinScale = -11; private const int MaxScale = 20; private const int MinBuckets = 2; private const long FractionMask = 4503599627370495; private const long ExponentMask = 9218868437227405312; private const int FractionWidth = 52; 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 Count => _count; internal double Sum => _sum; internal double MinMeasurement => _minMeasurement; internal double MaxMeasurement => _maxMeasurement; internal double ScalingFactor => _scalingFactor; internal long ZeroCount { get; set; } private unsafe static ReadOnlySpan<byte> LeadingZeroLookupTable => new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.85E702D46B2D96545206C3189AE524100555AAF96DF8EEBDD944CAFE6437ADAB, 256); 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) { if (!double.IsInfinity(value)) return !double.IsNaN(value); return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LeadingZero64(long value) { int num = (int)(value >> 32); if (num != 0) return LeadingZero32(num); return LeadingZero32((int)value) + 32; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LeadingZero32(int value) { short num = (short)(value >> 16); if (num != 0) return LeadingZero16(num); return LeadingZero16((short)value) + 16; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LeadingZero16(short value) { byte b = (byte)(value >> 8); if (b != 0) return LeadingZero8(b); return LeadingZero8((byte)value) + 8; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int LeadingZero8(byte value) { return LeadingZeroLookupTable[value]; } } }