Get CPU utilization by Process

Windows specific forum
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

I knocked together a little try based on GetProcessTimes_() which seems to work. It could probably be modified/improved, and there are other ways to accomplish it. I've included a little test program that uses around 3% CPU to test with, you can tweak the test prog to use more and see it change, comparing it to taskmanager. So far it's all correct here.

Code: Select all

;###################################################################################################################

Global gCurrentUsage.d

Procedure MonitorCPU(void)
  creation.FILETIME
  exit.FILETIME
  kernel.FILETIME
  user.FILETIME
  
  sysinfo.SYSTEM_INFO
  GetSystemInfo_(@sysinfo)
  numprocs = sysinfo\dwNumberOfProcessors

  h = OpenProcess_(#PROCESS_QUERY_INFORMATION, #False, GetCurrentProcessId_())  
  GetProcessTimes_(h,@creation,@exit,@kernel,@user)
  oldkernel=kernel\dwlowdatetime
  olduser=user\dwlowdatetime
  Delay(500)
  
  Repeat
    GetProcessTimes_(h,@creation,@exit,@kernel,@user)
    gCurrentUsage.d = ((((user\dwlowdatetime-olduser)+(kernel\dwlowdatetime-oldkernel))/500)/100)/numprocs
    olduser=user\dwlowdatetime
    oldkernel=kernel\dwlowdatetime    
    Delay (500)
  ForEver
EndProcedure

;###################################################################################################################


; Little test program - shows around 3% here, same as task mgr and debugger's CPU monitor

CreateThread(@MonitorCPU(),0)

InitSprite()
OpenWindow(0,0,0,640,480,"CPU Load Test",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
OpenWindowedScreen(WindowID(0),0,0,640,480,0,0,0)

CreateSprite(0, 128,128, #PB_Sprite_Texture)
StartDrawing(SpriteOutput(0))
  Box(0,0,128,128,#Red)
StopDrawing()
InitSprite3D()
CreateSprite3D(0,0)
CreateSprite3D(1,0)
CreateSprite3D(2,0)

Repeat
  ClearScreen(0)
  StartDrawing(ScreenOutput())
    DrawText(0,0,"CPU Usage: "+StrD(gCurrentUsage,2), #White, #Black)
  StopDrawing()
  Start3D()
    RotateSprite3D(0,1,1)
    RotateSprite3D(1,1,1)
    RotateSprite3D(2,1,1)
    DisplaySprite3D(0,100,100)
    DisplaySprite3D(1,250,100)
    DisplaySprite3D(2,400,100)
  Stop3D()
  FlipBuffers()
  Delay(1)
  ev = WindowEvent()
Until ev = #WM_CLOSE
You can put a timeBeginPeriod_(1) before the main loop and timeEndPeriod_(1) at the end and the CPU load goes to around 43% here, shown same in this proc as task mgr and CPU monitor utils.

This would actually be useful to make into a library and call it in your WIP projects to keep an eye on your CPU load, then you could take it out at release. I might make a little sticky window with a dial or something, could be fun.
Last edited by netmaestro on Sat Jun 06, 2009 1:25 am, edited 1 time in total.
BERESHEIT
dell_jockey
Enthusiast
Enthusiast
Posts: 767
Joined: Sat Jan 24, 2004 6:56 pm

Post by dell_jockey »

Hi,

I've added exponential smoothing to the routine above. The exponential moving average (EMA) is taken over the last #EMA_Samples, in this case an EMA over the last 20 samples that were taken with the original thread executing interval of 500ms. Effectively, you end up with an EMA over the last 10 seconds.

Enjoy!


Code: Select all

;################################################################################################################### 

Global gCurrentUsage.d

#EMA_Samples = 20 

Procedure.d EMA_smoothing(raw.d, samples.w)
  Static Alpha.d 
  Protected CurrentEMA.d
  Static PriorEMA.d
  
  Alpha.d = 2 / (samples.w + 1)
  CurrentEMA.d = priorEMA.d + (Alpha.d * (raw.d - priorEMA.d))
  PriorEMA.d = CurrentEMA.d
  
  ProcedureReturn CurrentEMA.d

EndProcedure


Procedure MonitorCPU(void) 
  creation.FILETIME 
  exit.FILETIME 
  kernel.FILETIME 
  user.FILETIME 
  
  sysinfo.SYSTEM_INFO 
  GetSystemInfo_(@sysinfo) 
  numprocs = sysinfo\dwNumberOfProcessors 

  h = OpenProcess_(#PROCESS_QUERY_INFORMATION, #False, GetCurrentProcessId_())  
  GetProcessTimes_(h,@creation,@exit,@kernel,@user) 
  oldkernel=kernel\dwlowdatetime 
  olduser=user\dwlowdatetime 
  Delay(500) 
  
  Repeat 
    GetProcessTimes_(h,@creation,@exit,@kernel,@user) 
    rawCurrentUsage.d = ((((user\dwlowdatetime-olduser)+(kernel\dwlowdatetime-oldkernel))/500)/100)/numprocs
    gCurrentUsage.d = EMA_smoothing(rawCurrentUsage.d, #EMA_Samples)
    olduser=user\dwlowdatetime 
    oldkernel=kernel\dwlowdatetime    
    Delay (500)
  ForEver 
EndProcedure 

;################################################################################################################### 


; Little test program - shows around 3% here, same as task mgr and debugger's CPU monitor 

CreateThread(@MonitorCPU(),0) 

InitSprite() 
OpenWindow(0,0,0,640,480,"CPU Load Test",#PB_Window_ScreenCentered|#PB_Window_SystemMenu) 
OpenWindowedScreen(WindowID(0),0,0,640,480,0,0,0) 

CreateSprite(0, 128,128, #PB_Sprite_Texture) 
StartDrawing(SpriteOutput(0)) 
  Box(0,0,128,128,#Red) 
StopDrawing() 
InitSprite3D() 
CreateSprite3D(0,0) 
CreateSprite3D(1,0) 
CreateSprite3D(2,0) 

Sprite3DQuality(1)

Repeat 
  ClearScreen(0) 
  StartDrawing(ScreenOutput()) 
    DrawText(0,0,"CPU Usage: "+StrD(gCurrentUsage,2)+"%", #White, #Black) 
  StopDrawing() 
  Start3D() 
    RotateSprite3D(0,1,1) 
    RotateSprite3D(1,1,1) 
    RotateSprite3D(2,1,1) 
    DisplaySprite3D(0,100,100) 
    DisplaySprite3D(1,250,100) 
    DisplaySprite3D(2,400,100) 
  Stop3D() 
  FlipBuffers() 
  Delay(1) 
  ev = WindowEvent() 
Until ev = #WM_CLOSE 
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
User avatar
Tenaja
Addict
Addict
Posts: 1959
Joined: Tue Nov 09, 2010 10:15 pm

Re: Get CPU utilization by Process

Post by Tenaja »

The help file does not have replacements for CreateSprite3D etc. easy to find. Not in search, not in history. Any of you graphics guys know how to fix Netmaestro's code?

Thanks.
User avatar
BasicallyPure
Enthusiast
Enthusiast
Posts: 539
Joined: Thu Mar 24, 2011 12:40 am
Location: Iowa, USA

Re: Get CPU utilization by Process

Post by BasicallyPure »

You can just use regular sprites.
Here is dell_jockey's code modified to work with regular sprites.
PB 5.40 LTS compatible.

Code: Select all

;################################################################################################################### 

Global gCurrentUsage.d

#EMA_Samples = 20 

Procedure.d EMA_smoothing(raw.d, samples.w)
  Static Alpha.d 
  Protected CurrentEMA.d
  Static PriorEMA.d
  
  Alpha.d = 2 / (samples.w + 1)
  CurrentEMA.d = priorEMA.d + (Alpha.d * (raw.d - priorEMA.d))
  PriorEMA.d = CurrentEMA.d
  
  ProcedureReturn CurrentEMA.d

EndProcedure


Procedure MonitorCPU(void) 
  creation.FILETIME 
  exit.FILETIME 
  kernel.FILETIME 
  user.FILETIME 
  
  sysinfo.SYSTEM_INFO 
  GetSystemInfo_(@sysinfo) 
  numprocs = sysinfo\dwNumberOfProcessors 

  h = OpenProcess_(#PROCESS_QUERY_INFORMATION, #False, GetCurrentProcessId_())  
  GetProcessTimes_(h,@creation,@exit,@kernel,@user) 
  oldkernel=kernel\dwlowdatetime 
  olduser=user\dwlowdatetime 
  Delay(500) 
  
  Repeat 
    GetProcessTimes_(h,@creation,@exit,@kernel,@user) 
    rawCurrentUsage.d = ((((user\dwlowdatetime-olduser)+(kernel\dwlowdatetime-oldkernel))/500)/100)/numprocs
    gCurrentUsage.d = EMA_smoothing(rawCurrentUsage.d, #EMA_Samples)
    olduser=user\dwlowdatetime 
    oldkernel=kernel\dwlowdatetime    
    Delay (500)
  ForEver 
EndProcedure 

;################################################################################################################### 


; Little test program - shows around 3% here, same as task mgr and debugger's CPU monitor 

CreateThread(@MonitorCPU(),0) 

InitSprite() 
OpenWindow(0,0,0,640,480,"CPU Load Test",#PB_Window_ScreenCentered|#PB_Window_SystemMenu) 
OpenWindowedScreen(WindowID(0),0,0,640,480,0,0,0) 

CreateSprite(0, 128, 128);CreateSprite(0, 128,128, #PB_Sprite_Texture) 
StartDrawing(SpriteOutput(0)) 
  Box(0,0,128,128,#Red) 
StopDrawing() 
;InitSprite3D() 
CopySprite(0,1);CreateSprite3D(0,0) 
CopySprite(0,2);CreateSprite3D(1,0) 
CopySprite(0,3);CreateSprite3D(2,0) 

;Sprite3DQuality(1)

Repeat 
  ClearScreen(0) 
  StartDrawing(ScreenOutput()) 
    DrawText(0,0,"CPU Usage: "+StrD(gCurrentUsage,2)+"%", #White, #Black) 
  StopDrawing() 
  ;Start3D() 
    RotateSprite(1,1,#PB_Relative);RotateSprite3D(0,1,1) 
    RotateSprite(2,1,#PB_Relative);RotateSprite3D(1,1,1) 
    RotateSprite(3,1,#PB_Relative);RotateSprite3D(2,1,1) 
    DisplaySprite(1,100,100);DisplaySprite3D(0,100,100) 
    DisplaySprite(2,250,100);DisplaySprite3D(1,250,100) 
    DisplaySprite(3,400,100);DisplaySprite3D(2,400,100) 
  ;Stop3D() 
  FlipBuffers() 
  Delay(1) 
  ev = WindowEvent() 
Until ev = #PB_Event_CloseWindow;#WM_CLOSE 
BasicallyPure
Until you know everything you know nothing, all you have is what you believe.
Post Reply