Using ConcurrentQueue for thread-safe Performance Bookkeeping.
- by Strenium
Just a small tidbit that's sprung up today. I had to book-keep and emit diagnostics for the average
thread performance in a highly-threaded code over a period of last X
number of calls and no more. Need of the day: a thread-safe,
self-managing stats container. Since .NET 4.0 introduced new
thread-safe 'Collections.Concurrent' objects and I've been using them
frequently - the one in particular seemed like a good fit for storing
each threads' performance data - ConcurrentQueue. But I wanted to store only the most recent X# of calls and since the ConcurrentQueue currently does not support size constraint I had to come up with my own generic version which attempts to restrict usage to numeric types only: unfortunately there is no IArithmetic-like interface
which constrains to only numeric types – so the constraints here
here aren't as elegant as they could be. (Note the use of the Average() method, of course you can use others as well as make your own). FIFO FixedSizedConcurrentQueue using System;using System.Collections.Concurrent;using System.Linq; namespace xxxxx.Data.Infrastructure{ [Serializable] public class FixedSizedConcurrentQueue<T> where T : struct, IConvertible, IComparable<T> { private FixedSizedConcurrentQueue() { } public FixedSizedConcurrentQueue(ConcurrentQueue<T> queue) { _queue = queue; } ConcurrentQueue<T> _queue = new ConcurrentQueue<T>(); public int Size { get { return _queue.Count; } } public double Average { get { return _queue.Average(arg => Convert.ToInt32(arg)); } } public int Limit { get; set; } public void Enqueue(T obj) { _queue.Enqueue(obj); lock (this) { T @out; while (_queue.Count > Limit) _queue.TryDequeue(out @out); } } } } The usage case is straight-forward, in this case I’m using a FIFO queue of maximum size of 200 to store doubles to which I simply Enqueue() the calculated rates: Usage var RateQueue = new FixedSizedConcurrentQueue<double>(new ConcurrentQueue<double>()) { Limit = 200 }; /* greater size == longer history */ That’s about it. Happy coding!