-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathWeightedProjectionSpeedCalculator.cs
More file actions
95 lines (80 loc) · 2.86 KB
/
WeightedProjectionSpeedCalculator.cs
File metadata and controls
95 lines (80 loc) · 2.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace LiquidProjections.Statistics
{
/// <summary>
/// Calculates the weighted speed in transactions per second.
/// </summary>
/// <remarks>
/// This class is not thread-safe.
/// A <see cref="Monitor"/> or another synchronization method should be used to ensure thread-safe usage.
/// </remarks>
public class WeightedProjectionSpeedCalculator
{
private readonly TimeSpan threshold;
private readonly int maxNrOfSamples;
private readonly Queue<float> samples = new Queue<float>();
private DateTime? lastSampleTimeStampUtc;
private long? lastCheckpoint;
public WeightedProjectionSpeedCalculator(int maxNrOfSamples, TimeSpan threshold)
{
this.maxNrOfSamples = maxNrOfSamples;
this.threshold = threshold;
}
private bool HasBaselineBeenSet => lastSampleTimeStampUtc != null;
public void Record(long checkpoint, DateTime timestampUtc)
{
if (HasBaselineBeenSet)
{
TimeSpan interval = timestampUtc - lastSampleTimeStampUtc.Value;
if (interval > threshold)
{
long delta = checkpoint - lastCheckpoint.Value;
samples.Enqueue((float) (delta / interval.TotalSeconds));
lastCheckpoint = checkpoint;
lastSampleTimeStampUtc = timestampUtc;
DiscardOlderSamples();
}
}
else
{
SetBaseline(checkpoint, timestampUtc);
}
}
private void SetBaseline(long checkpoint, DateTime timestampUtc)
{
lastCheckpoint = checkpoint;
lastSampleTimeStampUtc = timestampUtc;
}
private void DiscardOlderSamples()
{
while (samples.Count > maxNrOfSamples)
{
samples.Dequeue();
}
}
public float? GetWeightedSpeedIncluding(float sample)
{
return GetWeightedSpeed(samples.Concat(new[] { sample }));
}
public float? GetWeightedSpeed()
{
return GetWeightedSpeed(samples);
}
public float? GetWeightedSpeed(IEnumerable<float> effectiveSamples)
{
float weightedSum = 0;
int weights = 0;
int weight = 0;
foreach (float sample in effectiveSamples)
{
weight++;
weights += weight;
weightedSum += sample * weight;
}
return (weights == 0) ? (float?) null : weightedSum / weights;
}
}
}