Reading thread 'processor time' quickly

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi,

I need to be able to read the amount of processor time a thread has taken
up. So far I've found the following methods open to me:

1) Find the relevant ProcessThread in the current process'
ProcessThreadCollection and read the TotalProcessorTime.

2) Find the PerformanceCounter for the Thread category that relates to the
current thread, and use the NextSample() method to read the processor time
value. (I think this is pretty much what the first method is doing under the
hood anyway)

The problem is, both of those approaches are too slow for me, as I need to
find the value many times in quick succession (I'm using this to find out the
performance cost of methods)

From what I can tell about the PerformanceCounter approach, it re-gets *all*
the performance counter information for all the running threads and processes
every time I call NextSample, which isn't ideal. Is there any way just read
the value for the performance counter instance I'm actually interested in?

Cheers,
Mike
 
Hi Mike,

First of all, I would like to confirm my understanding of your issue. From
your description, I understand that you need to get the CPU time of a
certain thread. If there is any misunderstanding, please feel free to let
me know.

As far as I know, we can use both methods you mentioned to get the CPU
time. For the PerformanceCounter, we needn't get all the performance
information for all the running threads and processes every time. We can
specify the instance name, category and counter name for the performance
counter object. When we call NextValue method, it only returns the
information we need. Both of the two methods are fast enough on my machine.
Here is an example.

System.Diagnostics.PerformanceCounter pc = new
System.Diagnostics.PerformanceCounter("Thread", "% Processor Time");
pc.InstanceName = "WindowsApplication82/0";
float f = pc.NextValue();

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
Hi Kevin, thanks for your reply

Your understanding is correct, and your example is exactly one of the
approaches I've tried.

Unforfunately some of the methods that I'll need to measure execute very
quickly, and just calling NextValue() takes on average 0.02s-0.03s, which is
too slow for my needs.

I actually think this is a bit of a dead-end anyway, because from what I can
tell, the resolution of the counter seems to be in the centisecond range
anyway - i.e. when I execute it in quick succession, I get the same values
returned, then the reported values jump up by 0.01s.

As a point of note, I used reflector to have a peek to see what was going on
under the hood of the NextValue() method, and from what I could see it has to
re-create the Counter object, parse all of the instance data into a memory
structure and then find the instance I'm interested in. From the looks of
things this is because when you read a counter you get back all the instance
data in one big chunk of memory. (If you can get at the source code, you
will probably be able to see this in the constructor of
System.Diagnostics.CategorySample)

So, unless there is another way of reading thread timings at a higher
resolution, this may be a no-go!

Thanks,
Mike
 
Hi Mike,

It seems to be by design that the NextValue takes that much time to execute
in .NET framework. If you need the process to be faster, I think you can
try to use WMI instead, which gets value directly. You can try to post in
microsoft.public.win32.programmer.wmi newsgroup for wmi question. There
will be more professionals in that group to answer your question. HTH.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
Thanks Kevin, I've used WMI before, so hopefully I'll be able to work this out!

I'll post a quick sample if I get it sorted.

Cheers,
Mike
 
I promised a sample, so here it is in case anyone else ever wants it - you'll
need to include the System.Management namespace.

Sadly, the method call still seems to take around the same sort of time as
the performance counter approach - it's slightly faster, but still in the
same sort of ballpark - and the resolution seems to only be down to ~0.0001s.
I admit my needs are fairly extreme, and for most situations this will be
fine - I expect I'll be able to live with it though!

This sample adds together the user mode time and kernel mode time to get the
overall time.

====

string threadId = AppDomain.GetCurrentThreadId().ToString();
string processId =
System.Diagnostics.Process.GetCurrentProcess().Id.ToString();

using (ManagementObject testObject = new
ManagementObject(@"\\.\root\cimv2:Win32_Thread.Handle=""" + threadId +
"\",ProcessHandle=\"" + processId + "\""))
{
Console.WriteLine(((UInt64)testObject.Properties["UserModeTime"].Value +
(UInt64)testObject.Properties["KernelModeTime"].Value).ToString());
}

=======

Thanks for your time, Kevin,
Mike
 
You're welcome, Mike.

Thanks for sharing your experience with all the people here. If you have
any questions, please feel free to post them in the community.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
Back
Top