AutoHotkey Community

It is currently May 26th, 2012, 10:25 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 11 posts ] 
Author Message
PostPosted: August 24th, 2005, 9:07 am 
Code:
SetBatchLines, -1

SetFormat, float, 0.0

CoordMode, ToolTip, screen

period = 1000

loop
{
   idleTime = idleTime1
   GetIdleTime( idleTime )
   
   start := a_TickCount
   
   Sleep, %period%
   
   elapsed := a_TickCount-start
   
   idleTime = idleTime2
   GetIdleTime( idleTime )
   
   total_idle_ticks := ( idleTime2?ticks_high-idleTime1?ticks_high ) << 32
      total_idle_ticks := total_idle_ticks+( idleTime2?ticks_low-idleTime1?ticks_low )
      total_idle_ticks := total_idle_ticks*0.0001
   ppu_idle := total_idle_ticks/elapsed*100

   total := elapsed-total_idle_ticks
   ppu := 100-ppu_idle

   ToolTip, period = %period% (ideal)`nelapsed = %elapsed% (actual)`n`nppu = %total% ms (%ppu%`%)`nidle = %total_idle_ticks% ms (%ppu_idle%`%), 10, 10
}

ReadInteger( p_address, p_offset, p_size, p_hex=true )
{
    old_FormatInteger := a_FormatInteger

   if ( p_hex )
       SetFormat, integer, hex
   else
       SetFormat, integer, dec

   value = 0

   loop, %p_size%
       value := value+( *( ( p_address+p_offset )+( a_Index-1 ) ) << ( 8* ( a_Index-1 ) ) )

   SetFormat, integer, %old_FormatInteger%

   return, value
}

GetIdleTime( p_IdleTime )
{
   global
   local   success

   /*
   struct FILETIME {
      DWORD   dwLowDateTime;      uint4   0
      DWORD   dwHighDateTime;      uint4   4
   }
   */
   
   VarSetCapacity( %p_IdleTime%?ticks, 4+4 )
   
   success := DllCall( "kernel32.dll\GetSystemTimes", "uint", &%p_IdleTime%?ticks, "uint", 0, "uint", 0 )
   if ( ! success )
   {
      MsgBox, GetSystemTimes failed!
      
      ExitApp
   }
      
   %p_IdleTime%?ticks_low := ReadInteger( &%p_IdleTime%?ticks, 0, 4 )
   %p_IdleTime%?ticks_high := ReadInteger( &%p_IdleTime%?ticks, 4, 4 )
}


This method tracks the system idle time (i.e., the OS idle process). The assumption is that processor utilization can be determined by examining the difference between system idle time and elapsed time during any given period.

I have tested this against the "CPU Usage" and "System Idle Process - CPU Usage" statistics as presented by Process Explorer (PE) from SysInternals. In my testing I noticed that this method produces a processor utilization which fairly accurately tracks that given by PE. In fact, this method produces statistics which seem to anticipate that given by PE.

The code above is a proof-of-concept. A preferred implementation would likely use a timer to gather statistics and save them in a temporal list which could later be accessed as needed.

Anyway... no guarantees.


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: August 24th, 2005, 10:01 am 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
Hi shimanov,

Thank you so much for your script. That was one of the things I always wanted to have. I tested your script at it worked accourate enough. I have modified it. But in between I ran into trouble. It doesn't work any more. Could I ask you to have a look at it, please?

I added some msgbox into the code to see where it stops, but is was working, only when i click the msgboxes very fast, the code just stoped working. I do not know what I messed up, that causes such a behavior.

Thanks.
toralf

EDIT: Found it. It was just missing a #persistent. Now it works.

Code:
#Persistent
period = 1000
SetBatchLines, -1
SetFormat, float, 0.0
CoordMode, ToolTip, screen
SetTimer, CheckCPULoad, %period%
return

CheckCPULoad:
   start := a_TickCount
   elapsed := start - Laststart
   
   GetIdleTime( Low, High )
   
   If Laststart
     {
       Idle_ticks := ( High - Lasthigh ) << 32
       Idle_ticks := ( Idle_ticks + ( Low - Lastlow ) ) * 0.0001
       ppu_idle := Idle_ticks / elapsed * 100
     
       total := elapsed - Idle_ticks
       ppu := 100 - ppu_idle

       ToolTip,
         (LTrim
           period = %period% (ideal)
           elapsed = %elapsed% (actual)
         
           ppu = %total% ms (%ppu%`%)
           idle = %Idle_ticks% ms (%ppu_idle%`%)
         ), 10, 10
     }
   Laststart := start
   Lastlow := Low
   Lasthigh := High
return

GetIdleTime( ByRef Low, ByRef High )
  {
    VarSetCapacity( Ticks, 4+4 )
    success := DllCall( "kernel32.dll\GetSystemTimes", "uint", &Ticks, "uint", 0, "uint", 0 )
    if ( ! success )
      {
        MsgBox, GetSystemTimes failed!
        ExitApp
      }
       
    Low := ReadInteger( &Ticks, 0, 4 )
    High := ReadInteger( &Ticks, 4, 4 )
  }

ReadInteger( Address, Offset, Size )
  {
    old_FormatInteger := A_FormatInteger
    SetFormat, Integer, hex
    value = 0
    Loop, %Size%
        value := value + ( *( ( Address + Offset ) + ( A_Index - 1 ) ) << ( 8 * ( A_Index - 1 ) ) )
    SetFormat, Integer, %old_FormatInteger%
    Return, value
  }

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 24th, 2005, 1:21 pm 
Offline

Joined: March 2nd, 2004, 3:36 pm
Posts: 10720
Really nice. I tried it on my system and it seems exactly accurate. For example, it indicates 50% CPU utilitization when some other script runs an infinite loop with SetBatchLines 10ms, which is exactly what it is designed to use and what Task Manager says it uses.

Many people have asked for this, so thanks for spending the time to create and post it.


Report this post
Top
 Profile  
Reply with quote  
 Post subject: glad to help
PostPosted: August 25th, 2005, 7:35 am 
I am glad you have found value in my demo.

to: toralf

It's always good to know others can read your code. You have quickly transformed it to something of practical use. Thanks.

to: Chris

It is the least I can do. I have found AHk useful and purposeful. I appreciate your thoughtful design of the language, and the extensibility inherent to its design. Of course, the best part, is the AHk community. It draws you in, and then you have to participate. An enjoyable experience.


Report this post
Top
  
Reply with quote  
 Post subject: Re: glad to help
PostPosted: August 25th, 2005, 8:33 am 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
shimanov wrote:
It's always good to know others can read your code.
I admit I had some problems. You used a "?" inside your var names, which caused some irritations in my head.
And I still do not understand some of the math you did (bitshift and *). But I didn't mess with that. The rest was easy, just some re-structuring. I currently have it running all day in the upper left corner (0,0) just as a one-liner ToolTip. Very neat. Thanks for your participation. I can't wait for more shimanov-code. :)

_________________
Ciao
toralf
Image


Report this post
Top
 Profile  
Reply with quote  
PostPosted: August 26th, 2005, 11:01 am 
I forgot to mention, the "GetSystemTimes" routine requires, at minimum, Windows XP SP1.

toralf wrote:
You used a "?" inside your var names


I use "?" as a record operator to denote a field, as opposed to "." since that is unavailable.

toralf wrote:
And I still do not understand some of the math you did (bitshift and *).


First, all times are stored in ms. Second, most of the math is irrelevant -- my mistake. I forgot AHk (and ReadInteger) supports 64-bit signed integers.

Below is the revised version with some comments to explain why?:

Code:
SetBatchLines, -1

SetFormat, float, 0.0       ; set same display format as that in Process Explorer

CoordMode, ToolTip, screen

period = 1000               ; sample period

loop
{
    ; first sample
    idleTime = idleTime1
    GetIdleTime( idleTime )
   
    start := a_TickCount
   
    Sleep, %period%
   
    ; second sample
    elapsed := a_TickCount-start
   
    idleTime = idleTime2
    GetIdleTime( idleTime )
   
    total_idle_ticks := ( idleTime2?ticks-idleTime1?ticks )*0.0001  ; calculate difference and convert to ms
    ppu_idle := total_idle_ticks/elapsed*100                        ; ppu = Percentage Processor Usage
   
    total := elapsed-total_idle_ticks
    ppu := 100-ppu_idle
   
    ToolTip, period = %period% (ideal)`nelapsed = %elapsed% (actual)`n`nppu = %total% ms (%ppu%`%)`nidle = %total_idle_ticks% ms (%ppu_idle%`%), 10, 10
}

ReadInteger( p_address, p_offset, p_size, p_hex=true )
{
    old_FormatInteger := a_FormatInteger
   
    if ( p_hex )
       SetFormat, integer, hex
    else
       SetFormat, integer, dec
   
    value = 0
   
    loop, %p_size%
       value := value+( *( ( p_address+p_offset )+( a_Index-1 ) ) << ( 8* ( a_Index-1 ) ) )
   
    SetFormat, integer, %old_FormatInteger%
   
    return, value
}

GetIdleTime( p_IdleTime )
{
    global
    local   success
   
    /*
    struct FILETIME {
      DWORD   dwLowDateTime;      uint4   0
      DWORD   dwHighDateTime;      uint4   4
    }
    */
   
    VarSetCapacity( %p_IdleTime%?ticks, 4+4 )

    ; GetSystemTimes returns pointers to 64-bit signed integers (aka, ticks).  ticks are are the
    ;   number of 100-nanosecond intervals since January 1, 1601 -- a Microsoft thing.
    success := DllCall( "kernel32.dll\GetSystemTimes", "uint", &%p_IdleTime%?ticks, "uint", 0, "uint", 0 )
    if ( ! success )
    {
      MsgBox, GetSystemTimes failed!
     
      ExitApp
    }

    ; convert binary 64-bit signed integer to AHk format
    %p_IdleTime%?ticks := ReadInteger( &%p_IdleTime%?ticks, 0, 8 )
}


When evaluating discrepancies between the processor usage (PU) as given by this method and others, consider the following:

1. The sample period is set at 1 s.
2. The clock resolution for timing may only be 10 ms.
3. The system PU is tracking the PU of the System Idle Process. This may or may not be the statistic used by the Windows performance library to determine the system PU.
4. There may occur an offset, due to indirect tracking of the System Idle Process. Code within the Idle Process, will produce the most accurate results (i.e., discrepancy between retrieving system idle time and elapsed time).


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: November 8th, 2005, 10:27 pm 
Offline

Joined: December 15th, 2004, 10:24 pm
Posts: 303
Location: United States
This is a very nice script, which can be used, among other things, for keeping script/prog activity within a certain threshold. As far as i know, this cpu monitoring code is unique in the forum. Thanks for sharing it.

_________________
1) The Open Source Definition http://www.opensource.org/docs/definition_plain.php

2) Intuitive. Logical. Versatile. Adaptable. <<AutoHotkey>>


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 8th, 2005, 10:55 pm 
Offline

Joined: September 25th, 2005, 4:31 pm
Posts: 610
Decarlo110 wrote:
This is a very nice script, which can be used, among other things, for keeping script/prog activity within a certain threshold. As far as i know, this cpu monitoring code is unique in the forum. Thanks for sharing it.


Thanks. It was one of my early attempts to "get to know" Windows.

To monitor processor usage for a particular process, you may want to consider "GetProcessTimes".


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 9th, 2005, 1:38 am 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
Shimanov, is there a simple modification which calculates also the available free memory?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: November 9th, 2005, 2:33 am 
Offline

Joined: September 25th, 2005, 4:31 pm
Posts: 610
Laszlo wrote:
Shimanov, is there a simple modification which calculates also the available free memory?


Very simple indeed. Check this post.


Report this post
Top
 Profile  
Reply with quote  
PostPosted: February 22nd, 2010, 1:06 pm 
Offline

Joined: September 9th, 2008, 9:11 am
Posts: 5
Location: Czech rep.
This helpful script didn't count with multi core CPU. I have included 1 line, where I'v found out number of (logical, I hope that it is correct) processors and then only I'v divided total_idle_ticks by this:
Code:
EnvGet, ProcessorCount, NUMBER_OF_PROCESSORS
SetBatchLines, -1
SetFormat, float, 0.0       ; set same display format as that in Process Explorer
CoordMode, ToolTip, screen
period = 1000               ; sample period
loop
{
    ; first sample
    idleTime = idleTime1
    GetIdleTime( idleTime )
    start := a_TickCount
    Sleep, %period%
    ; second sample
    elapsed := a_TickCount-start
    idleTime = idleTime2
    GetIdleTime( idleTime )
    total_idle_ticks := ( idleTime2?ticks-idleTime1?ticks )*0.0001/ProcessorCount  ; calculate difference and convert to ms
    ppu_idle := total_idle_ticks/elapsed*100                        ; ppu = Percentage Processor Usage
    total := elapsed-total_idle_ticks
    ppu := 100-ppu_idle
    ToolTip, period = %period% (ideal)`nelapsed = %elapsed% (actual)`n`nppu = %total% ms (%ppu%`%)`nidle = %total_idle_ticks% ms (%ppu_idle%`%) , 10, 10
}

ReadInteger( p_address, p_offset, p_size, p_hex=true )
{
    old_FormatInteger := a_FormatInteger
    if ( p_hex )
       SetFormat, integer, hex
    else
       SetFormat, integer, dec
    value = 0
    loop, %p_size%
       value := value+( *( ( p_address+p_offset )+( a_Index-1 ) ) << ( 8* ( a_Index-1 ) ) )
    SetFormat, integer, %old_FormatInteger%
    return, value
}

GetIdleTime( p_IdleTime )
{
    global
    local   success
    /*
    struct FILETIME {
      DWORD   dwLowDateTime;      uint4   0
      DWORD   dwHighDateTime;      uint4   4
    }
    */
    VarSetCapacity( %p_IdleTime%?ticks, 4+4 )
    ; GetSystemTimes returns pointers to 64-bit signed integers (aka, ticks).  ticks are are the
    ;   number of 100-nanosecond intervals since January 1, 1601 -- a Microsoft thing.
    success := DllCall( "kernel32.dll\GetSystemTimes", "uint", &%p_IdleTime%?ticks, "uint", 0, "uint", 0 )
    if ( ! success )
    {
      MsgBox, GetSystemTimes failed!
      ExitApp
    }
    ; convert binary 64-bit signed integer to AHk format
    %p_IdleTime%?ticks := ReadInteger( &%p_IdleTime%?ticks, 0, 8 )
}


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: Cristi®, Google Feedfetcher, specter333 and 11 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group