Exponential Bucket Histogram - part 8 (#3505)

This commit is contained in:
Reiley Yang 2022-07-29 16:26:28 -07:00 committed by GitHub
parent cb6b7a82ce
commit f21afc8ce9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 82 deletions

View File

@ -89,50 +89,59 @@ internal sealed class CircularBufferBuckets
this.begin = index;
this.end = index;
this.trait[this.ModuloIndex(index)] += value;
return 0;
}
else if (index > this.end)
var begin = this.begin;
var end = this.end;
if (index > end)
{
var diff = index - this.begin;
if (diff >= capacity || diff < 0)
{
return CalculateScaleReduction(diff + 1, capacity);
}
this.end = index;
end = index;
}
else if (index < this.begin)
else if (index < begin)
{
var diff = this.end - index;
if (diff >= this.Capacity || diff < 0)
{
return CalculateScaleReduction(diff + 1, capacity);
}
this.begin = index;
begin = index;
}
else
{
this.trait[this.ModuloIndex(index)] += value;
return 0;
}
var diff = end - begin;
if (diff >= capacity || diff < 0)
{
return CalculateScaleReduction(begin, end, capacity);
}
this.begin = begin;
this.end = end;
this.trait[this.ModuloIndex(index)] += value;
return 0;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static int CalculateScaleReduction(int size, int capacity)
static int CalculateScaleReduction(int begin, int end, int capacity)
{
var shift = MathHelper.LeadingZero32(capacity);
Debug.Assert(capacity >= 2, "The capacity must be at least 2.");
if (size > 0)
var retval = 0;
var diff = end - begin;
while (diff >= capacity || diff < 0)
{
shift -= MathHelper.LeadingZero32(size);
begin >>= 1;
end >>= 1;
diff = end - begin;
retval++;
}
if (size > (capacity << shift))
{
shift++;
}
return shift;
return retval;
}
}
@ -256,18 +265,6 @@ internal sealed class CircularBufferBuckets
}
}
public override string ToString()
{
return nameof(CircularBufferBuckets)
+ "{"
+ nameof(this.Capacity) + "=" + this.Capacity + ", "
+ nameof(this.Size) + "=" + this.Size + ", "
+ nameof(this.begin) + "=" + this.begin + ", "
+ nameof(this.end) + "=" + this.end + ", "
+ (this.trait == null ? "null" : "{" + string.Join(", ", this.trait) + "}")
+ "}";
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int ModuloIndex(int value)
{

View File

@ -120,15 +120,6 @@ internal class ExponentialBucketHistogram
internal CircularBufferBuckets NegativeBuckets { get; }
/// <inheritdoc/>
public override string ToString()
{
return nameof(ExponentialBucketHistogram)
+ "{"
+ nameof(this.Scale) + "=" + this.Scale
+ "}";
}
/// <summary>
/// Maps a finite positive IEEE 754 double-precision floating-point
/// number to <c>Bucket[index] = ( base ^ index, base ^ (index + 1) ]</c>,
@ -189,36 +180,26 @@ internal class ExponentialBucketHistogram
var c = value.CompareTo(0);
if (c > 0)
{
var index = this.MapToIndex(value);
var n = this.PositiveBuckets.TryIncrement(index);
if (n != 0)
{
this.PositiveBuckets.ScaleDown(n);
this.NegativeBuckets.ScaleDown(n);
n = this.PositiveBuckets.TryIncrement(index);
Debug.Assert(n == 0, "Increment should always succeed after scale down.");
}
}
else if (c < 0)
{
var index = this.MapToIndex(-value);
var n = this.NegativeBuckets.TryIncrement(index);
if (n != 0)
{
this.PositiveBuckets.ScaleDown(n);
this.NegativeBuckets.ScaleDown(n);
n = this.NegativeBuckets.TryIncrement(index);
Debug.Assert(n == 0, "Increment should always succeed after scale down.");
}
}
else
if (c == 0)
{
this.ZeroCount++;
return;
}
var index = this.MapToIndex(c > 0 ? value : -value);
var buckets = c > 0 ? this.PositiveBuckets : this.NegativeBuckets;
var n = buckets.TryIncrement(index);
if (n == 0)
{
return;
}
this.PositiveBuckets.ScaleDown(n);
this.NegativeBuckets.ScaleDown(n);
this.Scale -= n;
n = buckets.TryIncrement(index >> n);
Debug.Assert(n == 0, "Increment should always succeed after scale down.");
}
}

View File

@ -101,18 +101,18 @@ public class CircularBufferBucketsTest
[Fact]
public void IntegerOverflow()
{
var buckets = new CircularBufferBuckets(1);
var buckets = new CircularBufferBuckets(2);
Assert.Equal(0, buckets.TryIncrement(int.MaxValue));
Assert.Equal(int.MaxValue, buckets.Offset);
Assert.Equal(1, buckets.Size);
Assert.Equal(31, buckets.TryIncrement(1));
Assert.Equal(31, buckets.TryIncrement(0));
Assert.Equal(32, buckets.TryIncrement(-1));
Assert.Equal(32, buckets.TryIncrement(int.MinValue + 1));
Assert.Equal(32, buckets.TryIncrement(int.MinValue));
Assert.Equal(30, buckets.TryIncrement(1));
Assert.Equal(30, buckets.TryIncrement(0));
Assert.Equal(31, buckets.TryIncrement(-1));
Assert.Equal(31, buckets.TryIncrement(int.MinValue + 1));
Assert.Equal(31, buckets.TryIncrement(int.MinValue));
}
[Fact]