OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
MetricsCollector.cs
Go to the documentation of this file.
1 using System;
2 using System.Diagnostics;
3 
4 namespace OpenSim.Framework
5 {
9  public class MetricsCollectorLong : MetricsCollector<long>
10  {
11  public MetricsCollectorLong(int windowSize, int numBuckets)
12  : base(windowSize, numBuckets)
13  {
14  }
15 
16  protected override long GetZero() { return 0; }
17 
18  protected override long Add(long a, long b) { return a + b; }
19  }
20 
21 
26  {
27  public MetricsCollectorTime(int windowSize, int numBuckets)
28  : base(windowSize, numBuckets)
29  {
30  }
31 
32  public void AddSample(Stopwatch timer)
33  {
34  long ticks = timer.ElapsedTicks;
35  if (ticks > 0)
36  AddSample(ticks);
37  }
38 
39  public TimeSpan GetSumTime()
40  {
41  return TimeSpan.FromMilliseconds((GetSum() * 1000) / Stopwatch.Frequency);
42  }
43  }
44 
45 
46  struct MetricsBucket<T>
47  {
48  public T value;
49  public int count;
50  }
51 
52 
64  public abstract class MetricsCollector<T>
65  {
66  private int bucketSize; // e.g. 3,000 ms
67 
68  private MetricsBucket<T>[] buckets;
69 
70  private int NumBuckets { get { return buckets.Length; } }
71 
72 
73  // The number of the current bucket, if we had an infinite number of buckets and didn't have to wrap around
74  long curBucketGlobal;
75 
76  // The total of all the buckets
77  T totalSum;
78  int totalCount;
79 
80 
85  protected abstract T GetZero();
86 
90  protected abstract T Add(T a, T b);
91 
92 
99  public MetricsCollector(int windowSize, int numBuckets)
100  {
101  bucketSize = windowSize / numBuckets;
102  buckets = new MetricsBucket<T>[numBuckets];
103  Reset();
104  }
105 
106  public void Reset()
107  {
108  ZeroBuckets(0, NumBuckets);
109  curBucketGlobal = GetNow() / bucketSize;
110  totalSum = GetZero();
111  totalCount = 0;
112  }
113 
114  public void AddSample(T sample)
115  {
116  MoveWindow();
117 
118  int curBucket = (int)(curBucketGlobal % NumBuckets);
119  buckets[curBucket].value = Add(buckets[curBucket].value, sample);
120  buckets[curBucket].count++;
121 
122  totalSum = Add(totalSum, sample);
123  totalCount++;
124  }
125 
129  public T GetSum()
130  {
131  // It might have been a while since we last added a sample, so we may need to adjust the window
132  MoveWindow();
133 
134  return totalSum;
135  }
136 
140  private long GetNow()
141  {
142  return DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
143  }
144 
148  private void ZeroBuckets(int offset, int num)
149  {
150  for (int i = 0; i < num; i++)
151  {
152  buckets[offset + i].value = GetZero();
153  buckets[offset + i].count = 0;
154  }
155  }
156 
165  private void MoveWindow()
166  {
167  long newBucketGlobal = GetNow() / bucketSize;
168  long bucketsDistance = newBucketGlobal - curBucketGlobal;
169 
170  if (bucketsDistance == 0)
171  {
172  // We're still on the same bucket as before
173  return;
174  }
175 
176  if (bucketsDistance >= NumBuckets)
177  {
178  // Discard everything
179  Reset();
180  return;
181  }
182 
183  int curBucket = (int)(curBucketGlobal % NumBuckets);
184  int newBucket = (int)(newBucketGlobal % NumBuckets);
185 
186 
187  // Clear all the buckets in this range: (cur, new]
188  int numToClear = (int)bucketsDistance;
189 
190  if (curBucket < NumBuckets - 1)
191  {
192  // Clear buckets at the end of the window
193  int num = Math.Min((int)bucketsDistance, NumBuckets - (curBucket + 1));
194  ZeroBuckets(curBucket + 1, num);
195  numToClear -= num;
196  }
197 
198  if (numToClear > 0)
199  {
200  // Clear buckets at the beginning of the window
201  ZeroBuckets(0, numToClear);
202  }
203 
204  // Move the "current bucket" pointer
205  curBucketGlobal = newBucketGlobal;
206 
207  RecalcTotal();
208  }
209 
210  private void RecalcTotal()
211  {
212  totalSum = GetZero();
213  totalCount = 0;
214 
215  for (int i = 0; i < NumBuckets; i++)
216  {
217  totalSum = Add(totalSum, buckets[i].value);
218  totalCount += buckets[i].count;
219  }
220  }
221 
222  }
223 }
A MetricsCollector for 'long' values.
MetricsCollectorLong(int windowSize, int numBuckets)
T GetSum()
Returns the total values in the collection window.
A MetricsCollector for time spans.
MetricsCollector(int windowSize, int numBuckets)
Creates a MetricsCollector.
override long Add(long a, long b)
override long GetZero()
Returns the default (zero) value.
MetricsCollectorTime(int windowSize, int numBuckets)