Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Performance Counter; .NET Locks & Threads - Current Queue Count Bu

74 views
Skip to first unread message

PeterM

unread,
Mar 1, 2005, 11:23:05 AM3/1/05
to
During the investigation of some multithreading issues we have in our
software, I have been attempting to use the NT performance counter;
Performance Counter; .NET Locks & Threads - Current Queue Count.

I noticed that when I monitor my .NET service this value continues to rise
steadily. It is my understanding that this represents the length of the
current Wait Queue. Also monitoring the physical and logical queues shows
that these two counters stay pretty much the same. This lead me to believe
that there is a bug in the Current Queue Length counter as it is far higher
that the number of logical or physical threads.

I investigated this rising count to discover that it is a specific call to
an overloaded member Monitor.Wait(object, int), where the int is the timeout
for the wait to attempt to re-acquire a lock on the object, instead of
waiting to be pulsed indefinitely is the cause. When the timeout occurs, the
thread gets the lock again and continues, but the Current Queue Length does
not get decremented.

I wrote a small test harness to prove my theory, and when using the
Monitor.Wait(object) member, when the object is pulsed and execution
continues, the Current Queue Length is decremented.

Is this an issue with the .NET runtime Wait Queue implementation, or is it
simply a problem with the performance counter implementation?

Brian Gideon

unread,
Mar 1, 2005, 1:24:24 PM3/1/05
to
Peter,

I notice the same thing. Here is the code I used.

class Test
{
private static Object _Lock = new Object();
private static int _Quantity = 0;

static void Main(string[] args)
{
Console.WriteLine("Press ENTER to go...");
Console.ReadLine();

Thread c = new Thread(new ThreadStart(Consumer));
c.IsBackground = true;
c.Start();

Thread p = new Thread(new ThreadStart(Producer));
p.IsBackground = true;
p.Start();

Console.ReadLine();
}

static void Producer()
{
while (true)
{
Monitor.Enter(_Lock);

while (_Quantity >= 10 && !Monitor.Wait(_Lock, 1));

Console.WriteLine("Producer: Quantity = " + ++_Quantity);

Monitor.Pulse(_Lock);

Monitor.Exit(_Lock);
}
}

static void Consumer()
{
while (true)
{
Monitor.Enter(_Lock);

while (_Quantity <= 0 && !Monitor.Wait(_Lock, 1));

Console.WriteLine("Consumer: Quantity = " + --_Quantity);

Monitor.Pulse(_Lock);

Monitor.Exit(_Lock);
}
}
}

As written the Current Queue Length counter (under .NET CLR
LocksAndThreads) goes up steadily. If I change the timeout from 1
millisecond to 1000 milliseconds so that the wait essentially never
times out then the counter appears normal. I'm using v1.1 of the .NET
Framework.

I think there is a bug in the counter implementation. Can someone else
confirm?

Brian

PeterM

unread,
Mar 2, 2005, 5:07:02 AM3/2/05
to
Hi Brian,
That's the one! Obviously the second (1000 MS) you're waiting gives your
thread scope to be pulsed. Obviously if it wasn't pulsed in this time then
the queue count would still rise. You probably know that already though.

It's very annoying because I needed to use this counter to verify our
software. When I turn round to the customer to tell them it's an MS bug.
Another garden path well exercised, and back to the drawing board ;-)

Cheers
Peter

Brian Gideon

unread,
Mar 2, 2005, 9:31:26 AM3/2/05
to
Peter,

I agree. The important thing here is that the performance counter is
not decremented only when the wait has timed out. I'm guessing the 1ms
wait didn't timeout all the time, but it was significantly more likely
to timeout than the 1000ms wait and that was the easiest way for me to
see the problem. Anyway, nice catch on your part. Perhaps someone
from Microsoft picked this up and logged it.

Brian

0 new messages