简体   繁体   中英

How to get CPU clock cycles used by process in kernel mode on windows?

As the title suggests I'm interested in obtaining CPU clock cycles used by a process in kernel mode only. I know there is an API called "QueryProcessCycleTime" which returns the CPU clock cycles used by the threads of the process. But this value includes cycles spent in both user mode and kernel mode. How can I obtain cycles spent in kernel mode only? Do I need to get this using Performance counters? If yes, which one I should use?

Thanks in advance for your answers.

I've just found an interesting article that describes almost what you ask for. It's on MSDN Internals .

They write there, that if you were using C# or C++/CLI, you could easily get that information from an instance of System.Diagnostic.Process class, pointed to the right PID. But it would give you a TimeSpan from the PrivilegedProcessorTime , so a "pretty time" instead of 'cycles'.

However, they also point out that all that .Net code is actually thin wrapper for unmanaged APIs, so you should be able to easily get it from native C++ too. They were ILDASM'ing that class to show what it calls, but the image is missing. I've just done the same, and it uses the GetProcessTimes from kernel32.dll

So, again, MSDN'ing it - it returns LPFILETIME structures. So, the 'pretty time', not 'cycles', again.

The description of this method points out that if you want to get the clock cycles, you should use QueryProcessCycleTime function. This actually returns the amount of clock cycles.. but user- and kernel-mode counted together.

Now, summing up:

  • you can read userTIME
  • you can read kernelTIME
  • you can read (user+kernel)CYCLES

So you have almost everything needed. By some simple math:

u_cycles = u_time * allcycles / (utime+ktime)
k_cycles = k_time * allcycles / (utime+ktime)

Of course this will be some approximation due to rounding etc.

Also, this will has a gotcha: you have to invoke two functions (GetTimes, QueryCycles) to get all the information, so there will be a slight delay between their readings, and therefore all your calculation will probably slip a little since the target process still runs and burns the time.

If you cannot allow for this (small?) noise in the measurement, I think you can circumvent it by temporarily suspending the process:

  • suspend the target
  • wait a little and ensure it is suspended
  • read first stats
  • read second stats
  • then resume the process and calculate values

I think this will ensure the two readings to be consistent, but in turn, each such reading will impact the overall performance of the measured process - so ie things like "wall time" will not be measureable any longer, unless you take some corrections for the time spent in suspension..

There may be some better way to get the separate clock cycles, but I have not found them, sorry. You could try looking inside the QueryProcessCycleTime and what source it reads the data from - maybe you are lucky and it reads A,B and returns A+B and maybe you could peek what are the sources. I have not checked it.

Take a look at GetProcessTimes . It'll give you the amount of kernel and user time your process has used.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM