Correct code to get CPU usage

  • Follow


Hi everyone:


I've been struggling to come up with a correct code to determine CPU usage 
on the Windows-based system. So far I came up with the following. The code 
is called internally from WM_TIMER message that is called once every 100 
milliseconds, but if compared with the Task Manager's CPU usage, it does not 
always match. What could be the reason for that?


int g_nCPU_usage_percent;    //Global variable
.....

SetTimer(m_hMainWndHandle, TIMER_ID, 100, NULL);

.....

void OnTimer(UINT nIDEvent)
{
 g_nCPU_usage_percent = GetCPU_Usage();
}


.....


int GetCPU_Usage()
{
 //RETURN:
 //  = Percentage value [0-100], or
 //  = -1 if not known, or error

 int nRes = -1;
 FILETIME ftIdle, ftKrnl, ftUsr;
 if(GetSystemTimes(&ftIdle, &ftKrnl, &ftUsr))
 {
  static BOOL bUsedOnce = FALSE;
  static ULONGLONG uOldIdle = 0;
  static ULONGLONG uOldKrnl = 0;
  static ULONGLONG uOldUsr = 0;

  ULONGLONG uIdle = ((ULONGLONG)ftIdle.dwHighDateTime << 32) | 
ftIdle.dwLowDateTime;
  ULONGLONG uKrnl = ((ULONGLONG)ftKrnl.dwHighDateTime << 32) | 
ftKrnl.dwLowDateTime;
  ULONGLONG uUsr = ((ULONGLONG)ftUsr.dwHighDateTime << 32) | 
ftUsr.dwLowDateTime;

  //Only if we have previous values
  if(bUsedOnce)
  {
   ULONGLONG uDiffIdle = uIdle - uOldIdle;
   ULONGLONG uDiffKrnl = uKrnl - uOldKrnl;
   ULONGLONG uDiffUsr = uUsr - uOldUsr;

   if(uDiffKrnl + uDiffUsr)
   {
    //Calculate percentage
    nRes = (int)((uDiffKrnl + uDiffUsr - uDiffIdle) * 100 / (uDiffKrnl + 
uDiffUsr));
   }
  }

  //Remember data
  bUsedOnce = TRUE;
  uOldIdle = uIdle;
  uOldKrnl = uKrnl;
  uOldUsr = uUsr;
 }

 return nRes;
}


0
Reply nki00 6/4/2010 11:06:43 PM

nki00 wrote:
> Hi everyone:
>
>
> I've been struggling to come up with a correct code to determine CPU usage
> on the Windows-based system. So far I came up with the following. The code
> is called internally from WM_TIMER message that is called once every 100
> milliseconds, but if compared with the Task Manager's CPU usage, it does not
> always match. What could be the reason for that?
>
>
> int g_nCPU_usage_percent;    //Global variable
> ....
>
> SetTimer(m_hMainWndHandle, TIMER_ID, 100, NULL);
>
> ....
>
> void OnTimer(UINT nIDEvent)
> {
>   g_nCPU_usage_percent = GetCPU_Usage();
> }
>
>
> ....
>
>
> int GetCPU_Usage()
> {
>   //RETURN:
>   //  = Percentage value [0-100], or
>   //  = -1 if not known, or error
>
>   int nRes = -1;
>   FILETIME ftIdle, ftKrnl, ftUsr;
>   if(GetSystemTimes(&ftIdle,&ftKrnl,&ftUsr))
>   {
>    static BOOL bUsedOnce = FALSE;
>    static ULONGLONG uOldIdle = 0;
>    static ULONGLONG uOldKrnl = 0;
>    static ULONGLONG uOldUsr = 0;
>
>    ULONGLONG uIdle = ((ULONGLONG)ftIdle.dwHighDateTime<<  32) |
> ftIdle.dwLowDateTime;
>    ULONGLONG uKrnl = ((ULONGLONG)ftKrnl.dwHighDateTime<<  32) |
> ftKrnl.dwLowDateTime;
>    ULONGLONG uUsr = ((ULONGLONG)ftUsr.dwHighDateTime<<  32) |
> ftUsr.dwLowDateTime;
>
>    //Only if we have previous values
>    if(bUsedOnce)
>    {
>     ULONGLONG uDiffIdle = uIdle - uOldIdle;
>     ULONGLONG uDiffKrnl = uKrnl - uOldKrnl;
>     ULONGLONG uDiffUsr = uUsr - uOldUsr;
>
>     if(uDiffKrnl + uDiffUsr)
>     {
>      //Calculate percentage
>      nRes = (int)((uDiffKrnl + uDiffUsr - uDiffIdle) * 100 / (uDiffKrnl +
> uDiffUsr));
>     }
>    }
>
>    //Remember data
>    bUsedOnce = TRUE;
>    uOldIdle = uIdle;
>    uOldKrnl = uKrnl;
>    uOldUsr = uUsr;
>   }
>
>   return nRes;
> }
>
>

I remember working on a process manager sime time ago in C#. It seems 
like I used WMI and PercentProcessorTime from 
Win32_PerfFormattedData_PerfOS_Processor to get processes' usage or 
something like that. Maybe you can try to look at that?

-- 
Regards,
Jackie
0
Reply Jackie 6/5/2010 9:43:14 AM


Jackie wrote:
> I remember working on a process manager sime time ago in C#. It seems
> like I used WMI and PercentProcessorTime from
> Win32_PerfFormattedData_PerfOS_Processor to get processes' usage or
> something like that. Maybe you can try to look at that?
>

Maybe you can look at Win32_PerfRawData_PerfOS_Processor as well. :)

-- 
Regards,
Jackie
0
Reply Jackie 6/5/2010 10:19:46 AM

nki00 wrote:
> Hi everyone:
>
>
> I've been struggling to come up with a correct code to determine CPU usage
> on the Windows-based system. So far I came up with the following. The code
> is called internally from WM_TIMER message that is called once every 100
> milliseconds, but if compared with the Task Manager's CPU usage, it does not
> always match. What could be the reason for that?
>

Tried to cancel my first replies. No idea if it worked.

Either way, I meant processors' usage and not processes' usage.
PercentProcessorTime from Win32_PerfFormattedData_PerfOS_Processor or 
Win32_PerfRawData_PerfOS_Processor (via WMI).
I hope it help.


-- 
Regards,
Jackie
0
Reply Jackie 6/5/2010 10:31:34 AM

On Fri, 4 Jun 2010 16:06:43 -0700, "nki00"
<lukkycharm1@gmail.com> wrote:

>Hi everyone:
>
>
>I've been struggling to come up with a correct code to determine CPU usage 
>on the Windows-based system. So far I came up with the following. The code 
>is called internally from WM_TIMER message that is called once every 100 
>milliseconds, but if compared with the Task Manager's CPU usage, it does not 
>always match. What could be the reason for that?
>
>
>int g_nCPU_usage_percent;    //Global variable
>....
>
>SetTimer(m_hMainWndHandle, TIMER_ID, 100, NULL);
>
>....
>
>void OnTimer(UINT nIDEvent)
>{
> g_nCPU_usage_percent = GetCPU_Usage();
>}
>
>
>....
>
>
>int GetCPU_Usage()
>{
> //RETURN:
> //  = Percentage value [0-100], or
> //  = -1 if not known, or error
>
> int nRes = -1;
> FILETIME ftIdle, ftKrnl, ftUsr;
> if(GetSystemTimes(&ftIdle, &ftKrnl, &ftUsr))
> {
>  static BOOL bUsedOnce = FALSE;
>  static ULONGLONG uOldIdle = 0;
>  static ULONGLONG uOldKrnl = 0;
>  static ULONGLONG uOldUsr = 0;
>
>  ULONGLONG uIdle = ((ULONGLONG)ftIdle.dwHighDateTime << 32) | 
>ftIdle.dwLowDateTime;
>  ULONGLONG uKrnl = ((ULONGLONG)ftKrnl.dwHighDateTime << 32) | 
>ftKrnl.dwLowDateTime;
>  ULONGLONG uUsr = ((ULONGLONG)ftUsr.dwHighDateTime << 32) | 
>ftUsr.dwLowDateTime;
>
>  //Only if we have previous values
>  if(bUsedOnce)
>  {
>   ULONGLONG uDiffIdle = uIdle - uOldIdle;
>   ULONGLONG uDiffKrnl = uKrnl - uOldKrnl;
>   ULONGLONG uDiffUsr = uUsr - uOldUsr;
>
>   if(uDiffKrnl + uDiffUsr)
>   {
>    //Calculate percentage
>    nRes = (int)((uDiffKrnl + uDiffUsr - uDiffIdle) * 100 / (uDiffKrnl + 
>uDiffUsr));
>   }
>  }
>
>  //Remember data
>  bUsedOnce = TRUE;
>  uOldIdle = uIdle;
>  uOldKrnl = uKrnl;
>  uOldUsr = uUsr;
> }
>
> return nRes;
>}

This approach is used by "ejor" at
<http://www.codeproject.com/KB/threads/Get_CPU_Usage.aspx>

But he warns that it doesn't give the correct
results with a multiprocessor system.  I didn't
download his complete code, but he says it has a
solution for that.

Best regards,


Bob Masta
 
              DAQARTA  v5.10
   Data AcQuisition And Real-Time Analysis
              www.daqarta.com
Scope, Spectrum, Spectrogram, Sound Level Meter
    Frequency Counter, FREE Signal Generator
           Pitch Track, Pitch-to-MIDI 
         DaqMusic - FREE MUSIC, Forever!
             (Some assembly required)
     Science (and fun!) with your sound card!
0
Reply N0Spam 6/5/2010 12:14:51 PM

nki00 wrote:
> Hi everyone:
> 
> 
> I've been struggling to come up with a correct code to determine CPU usage 
> on the Windows-based system. So far I came up with the following. The code 
> is called internally from WM_TIMER message that is called once every 100 
> milliseconds, but if compared with the Task Manager's CPU usage, it does not 
> always match. What could be the reason for that?

See this thread :
http://groups.google.fr/group/comp.os.ms-windows.programmer.win32/browse_thread/thread/a36b6af342c88b1/cd30a0aed8483a15?hl=fr&ie=UTF-8&q=_SYSTEM_INFORMATION_CLASS++cpu+usage#cd30a0aed8483a15
0
Reply alain 6/5/2010 1:32:54 PM

> Either way, I meant processors' usage and not processes' usage.
> PercentProcessorTime from Win32_PerfFormattedData_PerfOS_Processor or 
> Win32_PerfRawData_PerfOS_Processor (via WMI).
> I hope it help.
>
>
> -- 
> Regards,
> Jackie


Thanks!

I'll see what this does. Just curious though, how much of an imprint will a 
call to those WMI classes put on the system if, say, I do it once every 
second or so? I don't want to add too many CPU cycles to just run it, you 
know.


PS. I don't think one can edit or remove previous posts. 


0
Reply nki00 6/5/2010 8:11:23 PM

> This approach is used by "ejor" at
> <http://www.codeproject.com/KB/threads/Get_CPU_Usage.aspx>
>
> But he warns that it doesn't give the correct
> results with a multiprocessor system.  I didn't
> download his complete code, but he says it has a
> solution for that.

Bob, thanks, but I don't think I want to use something that doesn't work in 
multiprocessor environment (that's pretty much every CPU these days :) 


0
Reply nki00 6/5/2010 8:12:45 PM

> See this thread :

I think I found a solution to use NtQuerySystemInformation API myself, but
if you look at its description it looks like they may change it at any time,
so I try to steer clear from functions like that.




0
Reply nki00 6/5/2010 8:16:31 PM

nki00 wrote:
> Thanks!
>
> I'll see what this does. Just curious though, how much of an imprint will a
> call to those WMI classes put on the system if, say, I do it once every
> second or so? I don't want to add too many CPU cycles to just run it, you
> know.

I understand and agree. I am no expert on WMI but I read that you can 
improve performance by reusing the WMI connection somehow or reusing the 
locator. It also sounds logical to me that it will be some overhead with 
processing the query (parsing the same string and finding what you want, 
over and over again). I also read something about the LSASS process 
using "a lot" of the CPU under Windows Server 2008 with queries to 
remote machines. You could try to benchmark the methods you find (WMI, 
that internal function or other ways). I don't really know more than 
this, but I am kind of interested in the answer myself.

> PS. I don't think one can edit or remove previous posts.

Seems like it. I guess Thunderbird must be laughing at me for trying the 
"Cancel message" option. Had my doubts so at least I was not completely 
fooled.

--
Regards,
Jackie
0
Reply Jackie 6/5/2010 10:05:46 PM

> I don't really know more than this, but I am kind of interested in the 
> answer myself.
>

Thanks, Jackie. If I find more info I will post it here. 


0
Reply nki00 6/6/2010 8:09:50 PM

nki00 wrote:
>> I don't really know more than this, but I am kind of interested in the
>> answer myself.
>>
>
> Thanks, Jackie. If I find more info I will post it here.
>
>

Thank you as well. :)

-- 
Regards,
Jackie
0
Reply Jackie 6/6/2010 8:29:30 PM

On 05/06/2010 00:06, nki00 wrote:
> Hi everyone:
>
>
> I've been struggling to come up with a correct code to determine CPU usage
> on the Windows-based system. So far I came up with the following. The code
> is called internally from WM_TIMER message that is called once every 100
> milliseconds, but if compared with the Task Manager's CPU usage, it does not
> always match. What could be the reason for that?

How different is it?

CPU usage is an instantaneous value so two apps querying it will show 
roughly the same profile but may well give different values.

-- 
Dee Earley (dee.earley@icode.co.uk)
i-Catcher Development Team

iCode Systems

(Replies direct to my email address will be ignored.
Please reply to the group.)
0
Reply Dee 6/7/2010 8:07:22 AM

> How different is it?
>
> CPU usage is an instantaneous value so two apps querying it will show 
> roughly the same profile but may well give different values.

It's not that much different most of the times, but sometimes the Vista 
gadget will spike up when my app still shows a much lower value. But I agree 
that it's very hard to debug. 


0
Reply nki00 6/7/2010 9:35:49 AM

However, I do understand that you won't get per-processor or per-core 
usage info with GetSystemTimes.

-- 
Regards,
Jackie
0
Reply Jackie 6/7/2010 1:11:07 PM

14 Replies
1061 Views

(page loaded in 0.13 seconds)

Similiar Articles:


















7/24/2012 6:06:26 PM


Reply: