|
#region Copyright
// Diagnostic Explorer, a .Net diagnostic toolset
// Copyright (C) 2010 Cameron Elliot
//
// This file is part of Diagnostic Explorer.
//
// Diagnostic Explorer is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Diagnostic Explorer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Diagnostic Explorer. If not, see <http://www.gnu.org/licenses/>.
//
// http://diagexplorer.sourceforge.net/
#endregion
using System;
using System.Collections;
using System.Diagnostics;
using System.Linq;
using System.Timers;
namespace DiagnosticExplorer
{
public class RateCounter
{
private static Timer timer;
private static ArrayList counters = ArrayList.Synchronized(new ArrayList());
private DateTime lastCheck = DateTime.UtcNow;
private int[] counts;
private TimeSpan[] times;
private int index;
public event EventHandler<RateSampleEventArgs> SampleCollected;
static RateCounter()
{
timer = new Timer();
timer.Elapsed += Run;
timer.Interval = 1000;
}
public RateCounter(int secondsAverage)
{
counts = new int[secondsAverage];
times = new TimeSpan[secondsAverage];
lock (counters.SyncRoot)
{
counters.Add(new WeakReference(this));
if (counters.Count == 1)
timer.Start();
}
}
private void Increment()
{
lock (counts)
{
times[index % counts.Length] = DateTime.UtcNow - lastCheck;
CalcRate();
index++;
counts[index % counts.Length] = 0;
times[index % counts.Length] = TimeSpan.Zero;
lastCheck = DateTime.UtcNow;
InvokeSampleCollected();
}
}
private void InvokeSampleCollected()
{
try
{
EventHandler<RateSampleEventArgs> sampleCollectedHandler = SampleCollected;
if (sampleCollectedHandler != null)
{
RateSampleEventArgs args = new RateSampleEventArgs(Rate, GetRates(times.Length));
foreach (EventHandler<RateSampleEventArgs> handler in sampleCollectedHandler.GetInvocationList())
handler.BeginInvoke(this, args, null, null);
}
}
catch (Exception ex)
{
Trace.WriteLine(ex);
}
}
private void CalcRate()
{
double r = counts.Sum();
TimeSpan totalTime = times.Aggregate((t1, t2) => t1 + t2);
if (totalTime == TimeSpan.Zero)
Rate = 0;
else
Rate = r / totalTime.TotalSeconds;
}
public void Register(int count)
{
lock (counts)
{
if (count > 0)
Total += (ulong) count;
counts[index % counts.Length] += count;
}
}
/// <summary>
/// Gets the last n seconds rates
/// </summary>
/// <param name="seconds">The number of seconds worth of data to fetch</param>
/// <returns>A list of rates for the last n seconds, starting with the latest</returns>
public int[] GetRates(int seconds)
{
lock (counts)
{
return GetRates(seconds, index, counts);
}
}
internal static int[] GetRates(int seconds, int currentIndex, int[] values)
{
seconds = Math.Min(seconds, currentIndex);
int[] results = new int[seconds];
for (int i = 0; i < results.Length; i++)
results[i] = values[(currentIndex - 1 - i) % values.Length];
return results;
}
public double Rate { get; private set; }
public ulong Total { get; private set; }
private static void Run(object state, ElapsedEventArgs e)
{
try
{
lock (counters)
{
for (int i = counters.Count - 1; i >= 0; i--)
{
WeakReference r = (WeakReference) counters[i];
RateCounter counter = (RateCounter) r.Target;
if (counter == null)
counters.RemoveAt(i);
else
counter.Increment();
}
if (counters.Count == 0)
timer.Stop();
}
}
catch (Exception ex)
{
Trace.WriteLine(ex);
}
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I am a software developer originally from Auckland, New Zealand. I have lived and worked in London since 2005.