Geeks With Blogs
Alex's Blog-o-monium

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
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Linq;
  4.  
  5. namespace xxxxx.Data.Infrastructure
  6. {
  7.     [Serializable]
  8.     public class FixedSizedConcurrentQueue<T> where T : struct, IConvertible, IComparable<T>
  9.     {
  10.         private FixedSizedConcurrentQueue() { }
  11.  
  12.         public FixedSizedConcurrentQueue(ConcurrentQueue<T> queue)
  13.         {
  14.             _queue = queue;
  15.         }
  16.  
  17.         ConcurrentQueue<T> _queue = new ConcurrentQueue<T>();
  18.  
  19.         public int Size { get { return _queue.Count; } }
  20.         public double Average { get { return _queue.Average(arg => Convert.ToInt32(arg)); } }
  21.  
  22.         public int Limit { get; set; }
  23.         public void Enqueue(T obj)
  24.         {
  25.             _queue.Enqueue(obj);
  26.             lock (this)
  27.             {
  28.                 T @out;
  29.                 while (_queue.Count > Limit) _queue.TryDequeue(out @out);
  30.             }
  31.         }
  32.     }
  33.  
  34. }

 

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
  1. var RateQueue = new FixedSizedConcurrentQueue<double>(new ConcurrentQueue<double>()) { Limit = 200 }; /* greater size == longer history */

 

That’s about it. Happy coding!

Posted on Friday, April 6, 2012 12:03 AM | Back to top

Copyright © Strenium | Powered by: GeeksWithBlogs.net