Using ConcurrentQueue for thread-safe Performance Bookkeeping.
Posted
by Strenium
on Geeks with Blogs
See other posts from Geeks with Blogs
or by Strenium
Published on Fri, 06 Apr 2012 04:03:29 GMT
Indexed on
2012/04/06
5:30 UTC
Read the original article
Hit count: 223
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).
- 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:
- var RateQueue = new FixedSizedConcurrentQueue<double>(new ConcurrentQueue<double>()) { Limit = 200 }; /* greater size == longer history */
That’s about it. Happy coding!
© Geeks with Blogs or respective owner