Skip to content

Commit

Permalink
Fix: CircularTimeBuffer/TimeSlotResult was enforcing an incorrect inv…
Browse files Browse the repository at this point in the history
…ariant.
  • Loading branch information
lilith committed Sep 13, 2017
1 parent 3200cb7 commit ab91afb
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ void DequeueBuckets(long newHead)
var virtualDequeueCount = (toBucketIndexExclusive - fromBucketIndex);
var localDequeueCount = Math.Min(virtualDequeueCount,buckets);
Utilities.InterlockedMax(ref skippedResults, 0);
Interlocked.Add(ref skippedResults, virtualDequeueCount - localDequeueCount);
if (virtualDequeueCount > localDequeueCount)
{
Interlocked.Add(ref skippedResults, virtualDequeueCount - localDequeueCount);
}
for (int toDeque = 0; toDeque < localDequeueCount; toDeque++)
{
var bucketIndex = fromBucketIndex + toDeque;
Expand Down Expand Up @@ -105,7 +108,7 @@ public IEnumerable<long> DequeueValues()
{
var enumerableResults = DequeueResults();
// ReSharper disable once PossibleUnintendedReferenceComparison
return enumerableResults == Enumerable.Empty<TimeSlotResult>() ? Enumerable.Empty<long>() : enumerableResults.Select(r => r.Value.Value);
return enumerableResults == Enumerable.Empty<TimeSlotResult>() ? Enumerable.Empty<long>() : enumerableResults.Select(r => r.Value);
}

public override string ToString()
Expand All @@ -116,6 +119,8 @@ public override string ToString()

public bool Record(long ticks, long count)
{
if (ticks < 0) return false;

var newIndex = (ticks / ticksPerBucket);

Utilities.InterlockedMin(ref initialTail, newIndex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,19 @@ struct TimeSlotResult
{
public TimeSlotResult(long result, long slotBeginTicks)
{
this.value = result;
this.SlotBeginTicks = slotBeginTicks;
Value = result;
SlotBeginTicks = slotBeginTicks;
}

public long SlotBeginTicks { get; }

readonly long value;
public long? Value => SlotBeginTicks > 0 ? value : (long?)null;

public bool IsEmpty => SlotBeginTicks == 0;

/// <summary>
/// Empty does not denote a result of any kind; this is like null.
/// </summary>
public static readonly TimeSlotResult Empty = new TimeSlotResult();
public long SlotBeginTicks { get; }
public long Value { get; }

/// <summary>
/// <summary>
/// A zero result is a value of zero, not to be confused with Empty
/// </summary>
public static readonly TimeSlotResult ResultZero = new TimeSlotResult(0, 1);

public override string ToString()
{
return IsEmpty ? "(empty)" : $"[{value}] at {SlotBeginTicks}";
}
public override string ToString() => $"[{Value}] at {SlotBeginTicks}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,22 @@ public void CircularBufferTest()
Assert.Equal(23, results.Count());
Assert.Equal(new[] {0L, 1, 2, 3}, results.Take(4));
}

[Fact]
public void MultiIntervalTest()
{
NamedInterval[] Intervals = {
new NamedInterval { Unit = "second", Name = "Per Second", TicksDuration = Stopwatch.Frequency },
new NamedInterval { Unit = "minute", Name = "Per Minute", TicksDuration = Stopwatch.Frequency * 60 },
new NamedInterval { Unit = "15_mins", Name = "Per 15 Minutes", TicksDuration = Stopwatch.Frequency * 60 * 15 },
new NamedInterval { Unit = "hour", Name = "Per Hour", TicksDuration = Stopwatch.Frequency * 60 * 60 },
};
var s = new MultiIntervalStats(Intervals);
for (long i = Stopwatch.Frequency * -1000; i < Stopwatch.Frequency * 5000; i += Stopwatch.Frequency / 2)
{
s.Record(i, 1);
}
}

[Fact]
public void TestAddMulModHash()
Expand Down

0 comments on commit ab91afb

Please sign in to comment.