Page 1 of 2

CPU Usage Multi-core

Posted: Fri Feb 01, 2008 4:42 pm
by Gillou
Hello all,

In advance, sorry for my bad english... ;)

I write this program to create a CPU Monitor... But after many test with french purebasic community, it's appears that this code doesn't work with quad core. We can see that the result like this :

CPU0 : 210%
CPU1 : 222%
CPU2 : 254%
CPU3 : 228%
CPU TOTAL : 228%

If anyone have an idea on this problem, that will be very good.

Thanks by advance for your interest.


CPU Usage code
Structure SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
    IdleTime.q
    KernelTime.q
    UserTime.q
    DpcTime.q
    InterruptTime.q
    InterruptCount.q
EndStructure

#MaxCpus = 32

#SystemProcessorPerformanceInformation = 8
#SysProcPerfInfoLength = 48

#PROCESS_QUERY_INFORMATION = $400
#HUNDRED_NANOSEC = 10000000

Declare.l cpu_count()

Global Frequency.q, TimeStart.q

Global NumberOfProcessors = cpu_count()

Global Dim CpuInfo.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION(NumberOfProcessors)

Global Dim KernelTimesStart.d(NumberOfProcessors+1)
Global Dim UserTimesStart.d(NumberOfProcessors+1)
Global Dim IdleTimesStart.d(NumberOfProcessors+1)
Global Dim DpcTimesStart.d(NumberOfProcessors+1)
Global Dim InterruptTimesStart.d(NumberOfProcessors+1)

Global Dim KernelTimesStop.d(NumberOfProcessors+1)
Global Dim UserTimesStop.d(NumberOfProcessors+1)
Global Dim IdleTimesStop.d(NumberOfProcessors+1)
Global Dim DpcTimesStop.d(NumberOfProcessors+1)
Global Dim InterruptTimesStop.d(NumberOfProcessors+1)

Global Dim KernelTimesDelta.d(NumberOfProcessors+1)
Global Dim UserTimesDelta.d(NumberOfProcessors+1)
Global Dim IdleTimesDelta.d(NumberOfProcessors+1)

Global Dim CpuUsages.d(NumberOfProcessors+1)

Procedure.l cpu_count() ; Number of processors or cores
    Protected SI.SYSTEM_INFO
     GetSystemInfo_ (@SI)
     ProcedureReturn SI\dwNumberOfProcessors
EndProcedure

Procedure.s TimeConvert(time.q)
    hr.l = Round (time/36000000000, 0)
    time = time-(hr*36000000000)
    min.l = Round (time/600000000, 0)
    time = time-(min*600000000)
    sec.l = Round (time/10000000, 0)
    time = time-(sec*10000000)
    ms.l = Round (time/10000, 0)
     ProcedureReturn Str (hr)+ ":" + RSet ( Str (min), 2, "0" )+ ":" + RSet ( Str (sec), 2, "0" )+ ":" + RSet ( Str (ms), 3, "0" )
EndProcedure

Procedure GetProcessorsTimes(start = #True )
    Protected Lib
    Lib = OpenLibrary ( #PB_Any , "ntdll.dll" )
     If Lib
        Function = GetFunction (Lib, "NtQuerySystemInformation" )
         If CallFunctionFast (Function, #SystemProcessorPerformanceInformation , @CpuInfo(), #SysProcPerfInfoLength * #MaxCpus , @ret) = 0
             If ret/ #SysProcPerfInfoLength = NumberOfProcessors
                 If start = #True
                    KernelTimesStart(NumberOfProcessors) = 0
                    IdleTimesStart(NumberOfProcessors) = 0
                    UserTimesStart(NumberOfProcessors) = 0
                    DpcTimesStart(NumberOfProcessors) = 0
                    InterruptTimesStart(NumberOfProcessors) = 0
                     For i = 0 To NumberOfProcessors - 1
                        KernelTimesStart(i) = CpuInfo(i)\KernelTime
                        IdleTimesStart(i) = CpuInfo(i)\IdleTime
                        UserTimesStart(i) = CpuInfo(i)\UserTime
                        DpcTimesStart(i) = CpuInfo(i)\DpcTime
                        InterruptTimesStart(i) = CpuInfo(i)\InterruptTime
                        KernelTimesStart(NumberOfProcessors) = KernelTimesStart(NumberOfProcessors) + CpuInfo(i)\KernelTime
                        IdleTimesStart(NumberOfProcessors) = IdleTimesStart(NumberOfProcessors) + CpuInfo(i)\IdleTime
                        UserTimesStart(NumberOfProcessors) = UserTimesStart(NumberOfProcessors) + CpuInfo(i)\UserTime
                        DpcTimesStart(NumberOfProcessors) = DpcTimesStart(NumberOfProcessors) + CpuInfo(i)\DpcTime
                        InterruptTimesStart(NumberOfProcessors) = InterruptTimesStart(NumberOfProcessors) + CpuInfo(i)\InterruptTime
                     Next
                 Else
                    KernelTimesStop(NumberOfProcessors) = 0
                    IdleTimesStop(NumberOfProcessors) = 0
                    UserTimesStop(NumberOfProcessors) = 0
                    DpcTimesStop(NumberOfProcessors) = 0
                    InterruptTimesStop(NumberOfProcessors) = 0
                     For i = 0 To NumberOfProcessors - 1
                        KernelTimesStop(i) = CpuInfo(i)\KernelTime
                        IdleTimesStop(i) = CpuInfo(i)\IdleTime
                        UserTimesStop(i) = CpuInfo(i)\UserTime
                        DpcTimesStop(i) = CpuInfo(i)\DpcTime
                        InterruptTimesStop(i) = CpuInfo(i)\InterruptTime
                        KernelTimesStop(NumberOfProcessors) = KernelTimesStop(NumberOfProcessors) + CpuInfo(i)\KernelTime
                        IdleTimesStop(NumberOfProcessors) = IdleTimesStop(NumberOfProcessors) + CpuInfo(i)\IdleTime
                        UserTimesStop(NumberOfProcessors) = UserTimesStop(NumberOfProcessors) + CpuInfo(i)\UserTime
                        DpcTimesStop(NumberOfProcessors) = DpcTimesStop(NumberOfProcessors) + CpuInfo(i)\DpcTime
                        InterruptTimesStop(NumberOfProcessors) = InterruptTimesStop(NumberOfProcessors) + CpuInfo(i)\InterruptTime
                     Next
                 EndIf
             EndIf
         EndIf
         CloseLibrary (Lib)
     EndIf
EndProcedure

Procedure refresh()
    Protected CpuTime.d, CurTime.q, DiffTime.d
    
     QueryPerformanceCounter_ (@CurTime)
    GetProcessorsTimes( #False )
    CpuUsages(NumberOfProcessors) = 0
    
     For i = 0 To NumberOfProcessors - 1
        KernelTimesDelta(i) = KernelTimesStop(i) - KernelTimesStart(i)
        UserTimesDelta(i) = UserTimesStop(i) - UserTimesStart(i)
        IdleTimesDelta(i) = IdleTimesStop(i) - IdleTimesStart(i)
        CpuTime = (KernelTimesDelta(i) + UserTimesDelta(i) + IdleTimesDelta(i))
        DiffTime = (CurTime - TimeStart) / Frequency
         If DiffTime > 0 : CpuTime = ((CpuTime) / (DiffTime)) / NumberOfProcessors : EndIf
        CpuUsages(i) = (100 * (1 - CpuTime / #HUNDRED_NANOSEC ))
         If NumberOfProcessors = 1 : CpuUsages(i) = 100 + CpuUsages(i) : EndIf
         If CpuUsages(i) < 0 : CpuUsages(i) = 0 : EndIf
         ; If CpuUsages(i) > (100/NumberOfProcessors) : CpuUsages(i) = (100/NumberOfProcessors) : EndIf
         SetGadgetItemText (1, i, StrD (CpuUsages(i), 3), 2) ; Show percentage before adjusting to 100%
        CpuUsages(NumberOfProcessors) = CpuUsages(NumberOfProcessors) + CpuUsages(i)
        CpuUsages(i) = CpuUsages(i) * NumberOfProcessors
        KernelTimesStart(i) = KernelTimesStop(i)
        UserTimesStart(i) = UserTimesStop(i)
        IdleTimesStart(i) = IdleTimesStop(i)
        DpcTimesStart(i) = DpcTimesStop(i)
        InterruptTimesStart(i) = InterruptTimesStop(i)
         SetGadgetItemText (1, i, StrD (CpuUsages(i), 3), 1)
         SetGadgetItemText (1, i, TimeConvert(KernelTimesStart(i)), 3)
         SetGadgetItemText (1, i, TimeConvert(UserTimesStart(i)), 4)
         SetGadgetItemText (1, i, TimeConvert(IdleTimesStart(i)), 5)
         SetGadgetItemText (1, i, TimeConvert(DpcTimesStart(i)), 6)
         SetGadgetItemText (1, i, TimeConvert(InterruptTimesStart(i)), 7)
     Next
    
    KernelTimesStart(NumberOfProcessors) = KernelTimesStop(NumberOfProcessors)
    UserTimesStart(NumberOfProcessors) = UserTimesStop(NumberOfProcessors)
    IdleTimesStart(NumberOfProcessors) = IdleTimesStop(NumberOfProcessors)
    
     SetGadgetItemText (1, NumberOfProcessors, StrD (CpuUsages(NumberOfProcessors), 3), 1)
     SetGadgetItemText (1, NumberOfProcessors, TimeConvert(KernelTimesStart(NumberOfProcessors)), 3)
     SetGadgetItemText (1, NumberOfProcessors, TimeConvert(UserTimesStart(NumberOfProcessors)), 4)
     SetGadgetItemText (1, NumberOfProcessors, TimeConvert(IdleTimesStart(NumberOfProcessors)), 5)
     SetGadgetItemText (1, NumberOfProcessors, TimeConvert(DpcTimesStart(NumberOfProcessors)), 6)
     SetGadgetItemText (1, NumberOfProcessors, TimeConvert(InterruptTimesStart(NumberOfProcessors)), 7)
    
    TimeStart = CurTime
EndProcedure

QueryPerformanceFrequency_ (@Frequency)
QueryPerformanceCounter_ (@TimeStart)

GetProcessorsTimes()

Win = OpenWindow ( #PB_Any , 0, 0, 635, 140, "CPU Usage Multi-Processors" , #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget )
If IsWindow (Win) And CreateGadgetList ( WindowID (Win))
     ListIconGadget (1, 10, 10, 615, 120, "CPU" , 75)
     AddGadgetColumn (1, 1, "% Usage" , 60)
     AddGadgetColumn (1, 2, "% (" + Str (100/NumberOfProcessors)+ ")" , 60)
     AddGadgetColumn (1, 3, "Kernel Time" , 80)
     AddGadgetColumn (1, 4, "User Time" , 80)
     AddGadgetColumn (1, 5, "Idle Time" , 80)
     AddGadgetColumn (1, 6, "Dpc Time" , 80)
     AddGadgetColumn (1, 7, "Interrupt Time" , 80)
    
     For i=0 To NumberOfProcessors-1
         AddGadgetItem (1, -1, "CPU " + Str (i))
     Next
     AddGadgetItem (1, NumberOfProcessors, "CPU TOTAL" )
    
     SetTimer_ ( WindowID (Win), 1, 1000, @refresh())
     Repeat
         Select WaitWindowEvent ()
             Case #PB_Event_CloseWindow
                Quit = 1
         EndSelect
     Until Quit = 1
     KillTimer_ ( WindowID (Win), 1)
EndIf



Test code to change the processor's affinity
Declare set_affinity(CPU)
Declare cpu_count()

; Open the Task Manager
Shell_TrayWnd = FindWindow_ ( "Shell_TrayWnd" , NULL)
Result = SendMessage_ (Shell_TrayWnd, $111, 420, 0)

; Return name of process in task manager
ExeName.s = Space (255) : GetModuleFileName_ (0, @ExeName, 255)

Win = OpenWindow ( #PB_Any , 0, 0, 400, 200, "Multi-Core Test - " + GetFilePart (ExeName), #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget )
If Win And CreateGadgetList ( WindowID (Win))
     TextGadget ( #PB_Any , 10, 10, 180, 20, "Number of processors : " + Str (cpu_count()))
    CPU = 0
     For X = 0 To cpu_count()-1
         CheckBoxGadget (X, 10, (X*25)+30, 180, 20, "CPU " + Str (X))
        CPU + Pow (2, X)
         SetGadgetState (X, 1)
     Next
    set_affinity(CPU)
     Repeat
         Select WindowEvent () ; Just to use processors for multi-core test with WindowEvent
             Case #PB_Event_Gadget
                Event = EventGadget ()
                CPU = 0
                 For X = 0 To cpu_count()-1
                     If GetGadgetState (X) = 1
                        CPU + Pow (2, X)
                     EndIf
                 Next
                 If CPU = 0
                    set_affinity(1)
                     SetGadgetState (0, 1)
                 Else
                    set_affinity(CPU)
                 EndIf
             Case #PB_Event_CloseWindow
                Quit = 1
         EndSelect
     Until Quit = 1
EndIf

ProcedureDLL.l cpu_count() ; Number of processors or cores
    Protected SI.SYSTEM_INFO
     GetSystemInfo_ (@SI)
     ProcedureReturn SI\dwNumberOfProcessors
EndProcedure
 
Procedure get_affinity(mode = 0) ; Mode = 0 : Process, Mode = 1 : System
    Protected lpProcessAffinityMask.l, lpSystemAffinityMask.l, hProcess.l
    
    hProcess = GetCurrentProcess_ ()
     GetProcessAffinityMask_ (hProcess,@lpProcessAffinityMask,@lpSystemAffinityMask)
     If mode = 0
         ProcedureReturn lpProcessAffinityMask
     Else
         ProcedureReturn lpSystemAffinityMask
     EndIf
EndProcedure

Procedure set_affinity(CPU)
    Protected lpProcessAffinityMask.l, lpSystemAffinityMask.l, hProcess.l
    
    hProcess = GetCurrentProcess_ ()
    succes = SetProcessAffinityMask_ (hProcess, CPU)
    
     ProcedureReturn succes
EndProcedure

Posted: Mon Feb 04, 2008 1:23 am
by Gillou
No idea?

If you know website where i can find information on CPU Usage on quad core or if you have an idea by other way to get the CPU Usage that will be great ;)

Posted: Sat Mar 22, 2008 11:24 am
by Helle
The PDH.DLL ("Performance Data Helper") is in \System32 since W2k. This is a Code with this (in German, sorry):

Code: Select all

;- CPU-Auslastung-Ermittlung mit der PDH.DLL, auch für Multi-Core-CPU´s 
;- W2k, WXP, Vista(?) 
;- "Helle" Klaus Helbing, 22.03.2008, PB4.10 
;- Soll nur schmucklos die einfache Machbarkeit zeigen! 

Global hQuery.l
Global RetVal.l
Global Core.l

Global SI.SYSTEM_INFO

;#PDH_CSTATUS_VALID_DATA = $0
#PDH_CSTATUS_NEW_DATA = $1

;ich mag keine Structuren...
Core = AllocateMemory(64)              ;für max. 4 Cores, 0-15=Counter, 16-31=PdhStatus, 32-63=dblValue 

Prototype.d ProtoValue(Para1.l, Para2.l)    ;CallFunction geht nicht wegen Double-Rückgabewert! 

Procedure.l cpu_count()                ;Anzahl der Cores ermittlen 
  GetSystemInfo_(@SI) 
  ProcedureReturn SI\dwNumberOfProcessors 
EndProcedure 

If OpenLibrary(0, "PDH.DLL")           ;MS-File in \System32 
  RetVal = CallFunction(0, "PdhOpenQuery", 0, 1, @hQuery)
  If RetVal
    MessageRequester("Fehler !", "Aufruf von PdhOpenQuery fehlgeschlagen!")  
  EndIf
 
  cpu_count()
 
  For i=0 To SI\dwNumberOfProcessors - 1
    RetVal = CallFunction(0, "PdhVbAddCounter", hQuery, "\Prozessor("+ Str(i) +")\Prozessorzeit (%)", Core+4*i)   ;Counter
    If RetVal
      MessageRequester("Fehler !", "Aufruf von PdhVbAddCounter für Core"+ Str(i) +" fehlgeschlagen!")  
    EndIf
  Next 
  
  Repeat 
    CallFunction(0, "PdhCollectQueryData", hQuery)
    Auslastung$=""
    For i=0 To SI\dwNumberOfProcessors - 1
      Value.ProtoValue = GetFunction(0, "PdhVbGetDoubleCounterValue")
      A.l=i<<3
      B.d=Core+32+A                    ;dblValue 
      B = Value(PeekL(Core+4*i), Core+16+i<<2)
      Auslastung$ + "Auslastung Core" + Str(i)+" = "+ StrD(B, 2) + "%" + Space(20)
      If PeekL(Core+16+i<<2) > #PDH_CSTATUS_NEW_DATA  ;s.o.
        A = -1                         ;war kein gültiger Wert
        Break
      EndIf     
    Next 

    If A <> -1
      Debug Auslastung$
    EndIf
    Delay(500)
  ForEver 

  CallFunction(0, "PdhCloseQuery", hQuery)
  CloseLibrary(0)
EndIf 
Gruss
Helle

Posted: Mon Mar 24, 2008 12:48 pm
by dell_jockey
Danke schön, Helle !

Posted: Mon Mar 24, 2008 1:03 pm
by ts-soft
You can import the functions from pdh.lib

And it works on vista, thanks

English Version

Posted: Mon Mar 24, 2008 5:10 pm
by SMartin
Here's an English versions of Helle's code.

Code: Select all

;- CPU extent of utilization determination with the PDH.DLL, also for Multi core CPU's
;- Win2k, WinXP, Vista(?) 
;- "Helle" Klaus Helbing, 22.03.2008, PB4.10 
;- Simply intended to show the feasibility

Global hQuery.l 
Global RetVal.l 
Global Core.l 

Global SI.SYSTEM_INFO 

;#PDH_CSTATUS_VALID_DATA = $0 
#PDH_CSTATUS_NEW_DATA = $1 

;I do not like Structures....
Core = AllocateMemory(64)             ;for max. 4 cores, 0-15=Counter, 16-31=PdhStatus, 32-63=dblValue

Prototype.d ProtoValue(Para1.l, Para2.l)    ;CallFunction does not work because of a double return value!

;Number of cores 
Procedure.l cpu_count()            
  GetSystemInfo_(@SI) 
  ProcedureReturn SI\dwNumberOfProcessors 
EndProcedure 

If OpenLibrary(0, "PDH.DLL")           ;MS-File in \System32 
  RetVal = CallFunction(0, "PdhOpenQuery", 0, 1, @hQuery) 
  If RetVal 
    MessageRequester("Error !", "Unable to call function PdhOpenQuery()!")  
  EndIf 
  
  cpu_count() 
  
  For i=0 To SI\dwNumberOfProcessors - 1 
    RetVal = CallFunction(0, "PdhVbAddCounter", hQuery, "\Processor(" + Str(i) + ")\% Processor Time", Core+4*i)   ;Counter 
    If RetVal 
      MessageRequester("Error !", "Call to function PdhVbAddCounter() for core "+ Str(i) +" failed!")  
    EndIf 
  Next 
  
  Repeat 
    CallFunction(0, "PdhCollectQueryData", hQuery) 
    ExtentOfUtilization$="" 
    For i=0 To SI\dwNumberOfProcessors - 1 
      Value.ProtoValue = GetFunction(0, "PdhVbGetDoubleCounterValue") 
      A.l=i<<3 
      B.d=Core+32+A                    ;dblValue 
      B = Value(PeekL(Core+4*i), Core+16+i<<2) 
      ExtentOfUtilization$ + "Extent of core utilization " + Str(i)+" = "+ StrD(B, 2) + "%" + Space(20) 
      If PeekL(Core+16+i<<2) > #PDH_CSTATUS_NEW_DATA  ;s.o. 
        A = -1                         ;invalid value
        Break 
      EndIf      
    Next 

    If A <> -1 
      Debug ExtentOfUtilization$ 
    EndIf 
    Delay(500) 
  ForEver 

  CallFunction(0, "PdhCloseQuery", hQuery) 
  CloseLibrary(0) 
EndIf 

Re: CPU Usage Multi-core

Posted: Fri Oct 05, 2012 1:30 am
by chris319
This version compiles and runs:

Code: Select all

    ;- CPU extent of utilization determination with the PDH.DLL, also for Multi core CPU's
    ;- Win2k, WinXP, Vista(?)
    ;- "Helle" Klaus Helbing, 22.03.2008, PB4.10
    ;- Simply intended to show the feasibility

    Global hQuery.l
    Global RetVal.l
    Global Core.l

    Global SI.SYSTEM_INFO

    ;#PDH_CSTATUS_VALID_DATA = $0
    #PDH_CSTATUS_NEW_DATA = $1

    ;I do not like Structures....
    Core = AllocateMemory(64) ;for max. 4 cores, 0-15=Counter, 16-31=PdhStatus, 32-63=dblValue

    Prototype.d ProtoValue(Para1.l, Para2.l) ;CallFunction does not work because of a double return value!

    ;Number of cores
    Procedure.l cpu_count()           
      GetSystemInfo_(@SI)
      ProcedureReturn SI\dwNumberOfProcessors
    EndProcedure
    
OpenConsole()
    
    If OpenLibrary(0, "PDH.DLL") = 0         ;MS-File in \System32
      MessageRequester("Error", "Unable to open PDH.DLL.")
      CloseConsole()
      End
    EndIf
  
      RetVal = CallFunction(0, "PdhOpenQuery", 0, 1, @hQuery)
      If RetVal
        MessageRequester("Error", "Unable to call function PdhOpenQuery().") 
      EndIf
     
      cpu_count()
     
; Function PdhVbAddCounter( _ ByVal QueryHandle As Long, _ ByVal CounterPath As String, _ ByVal CounterHandle As Long _ ) As Long
; Parameters
; 
; QueryHandle
; ID of the query To which this counter is To be assigned. This value is returned by the PdhVbOpenQuery function.
; 
; CounterPath
; Text string that specifies the name of the counter path To add To the query. The contents of this string must be a valid counter path, As obtained from the counter browser Or other source.
; 
; CounterHandle
; Unique reference that identifies this counter in the query. This variable must be initialized To zero before the function is called. It contains a valid value on Return only If the function completes successfully.
      For i = 0 To SI\dwNumberOfProcessors - 1
;        RetVal = CallFunction(0, "PdhVbAddCounter", hQuery, "\Processor(" + Str(i) + ")\% Processor Time", Core+4*i)   ;Counter
        RetVal = CallFunction(hQuery, "\Processor(" + Str(i) + ")\% Processor Time", Core + 4 * i)   ;Counter

        If RetVal
          MessageRequester("Error", "Call to function PdhVbAddCounter() for core "+ Str(i) +" failed.") 
        EndIf
      Next
     
      Repeat
        CallFunction(0, "PdhCollectQueryData", hQuery)
        ExtentOfUtilization$=""
        For i=0 To SI\dwNumberOfProcessors - 1
          Value.ProtoValue = GetFunction(0, "PdhVbGetDoubleCounterValue")
          A.l=i<<3
          B.d=Core+32+A ;dblValue
          B = Value(PeekL(Core+4*i), Core+16+i<<2)
;          ExtentOfUtilization$ + "Extent of core utilization " + Str(i)+" = "+ StrD(B, 2) + "%" + Chr(9) ;Space(20)
          ExtentOfUtilization$ + "Core "  + Str(i) + ": " + StrD(B, 2) + "%" + Chr(9) ;Space(20)
          If PeekL(Core+16+i<<2) > #PDH_CSTATUS_NEW_DATA  ;s.o.
            A = -1 ;invalid value
            Break
          EndIf     
        Next

        If A <> -1
          PrintN(ExtentOfUtilization$)
        EndIf
        Delay(500)
        If Inkey() <> "": Break: EndIf
      ForEver

      CallFunction(0, "PdhCloseQuery", hQuery)
      CloseLibrary(0)
      CloseConsole()
      End

Re: CPU Usage Multi-core

Posted: Fri Oct 05, 2012 10:05 am
by GG
Number of cores well detected, but I've always 0.00% per core whatever I do. :shock:

Anyone has the same symptom ?

Pb 4.61 / Windows XP 32 bits

Re: CPU Usage Multi-core

Posted: Fri Oct 05, 2012 2:20 pm
by blueb
GG wrote:Number of cores well detected, but I've always 0.00% per core whatever I do. :shock:

Anyone has the same symptom ?
Yes.. the same results

Purebasic 5.0b3 (x86) - Windows 7 Pro 64 SP1

Re: CPU Usage Multi-core

Posted: Sat Oct 06, 2012 3:44 am
by Zebuddi123
Hi to All

RE: Test code

Declare cpu_count() ; .l missing from Declare


Thanks for sharing

Zebuddi. :D

Re: CPU Usage Multi-core

Posted: Sat Oct 06, 2012 1:17 pm
by Helle
Aua, my youth :mrgreen: !
Check this (my German version):

Code: Select all

;- CPU-Auslastung-Ermittlung mit der PDH.DLL
;- "Helle" Klaus Helbing, 09.10.2012, tested with PB4.61 (x64), Win7/64 and PB4.61 (x86), Win-XP
;- Use Debug

If OpenLibrary(0, "PDH.DLL")                     ;MS-File in \System32
  SI.SYSTEM_INFO
  #PDH_CSTATUS_NEW_DATA = $1
  #PROCESSOR_ARCHITECTURE_AMD64 = $9

  GetSystemInfo_(@SI)                            ;Anzahl der Cores ermitteln
  AnzCore.l = SI\dwNumberOfProcessors
  Is64.i = SI\wProcessorArchitecture             ;w -> i
  Buffer.i = AllocateMemory(8 * AnzCore)
  CoreLast.d
  CoreLast64.d
  hQuery.l

  Prototype.l ProtoOpenQuery(Para1.l)
  Prototype.l ProtoCloseQuery(Para1.l)
  Prototype.l ProtoCollectData(Para1.l)
  Prototype.d ProtoAuslastung(Para1.l, Para2.l)
  Prototype.l ProtoAddCounter(Para1.l, Para2.i, Para3.i)

  Lang = GetSystemDefaultLangID_() & $FFFF
  Select Lang
    Case $407                                    ;GE
      P1$ = "Prozessor"
      P2$ = "Prozessorzeit" 
    Case $409                                    ;EN_US   ckeck it :-)!
      P1$ = "Processor"
      P2$ = "Processor Time"
    Case $40C                                    ;FR      check it :-)!
      P1$ = "Processeur"
      P2$ = "temps Processeur"
    ;.....  Other Languages

  EndSelect

  OpenQuery.ProtoOpenQuery = GetFunction(0, "PdhVbOpenQuery")
  CloseQuery.ProtoCloseQuery = GetFunction(0, "PdhCloseQuery")       ;PdhVbCloseQuery z.B. nicht für Server 2003 !
  CollectData.ProtoCollectData = GetFunction(0, "PdhCollectQueryData")
  AddCounter.ProtoAddCounter = GetFunction(0, "PdhVbAddCounter")
  Auslastung.ProtoAuslastung = GetFunction(0, "PdhVbGetDoubleCounterValue")
 
  RetVal = OpenQuery(@hQuery)
   
  If RetVal
    MessageRequester("Fehler !", "Aufruf von PdhVbOpenQuery fehlgeschlagen!")  ;Error-Message OpenQuery
    End
  EndIf

  For i = 0 To AnzCore - 1
    Proz$ = "\" + P1$ + "(" + Str(i) + ")\" + P2$ + " (%)"
    RetVal = AddCounter(hQuery, @Proz$, Buffer + (i << 2))
    If RetVal
      MessageRequester("Fehler !", "Aufruf von PdhVbAddCounter für Core"+ Str(i) + " fehlgeschlagen!")  ;Error-Message AddCounter
      ;End
    EndIf
  Next
 
  Repeat
    CollectData(hQuery)
    Auslastung$ = ""
    For i = 0 To AnzCore - 1
      CoreLast = Auslastung(PeekL(Buffer + (4 * i)), PeekL(Buffer + (4 * AnzCore) + (i << 2)))
      !movsd [v_CoreLast64],xmm0                 ;64-Bit-DLL: Float-/Double-Return-Value in XMM0!
      If Is64 = #PROCESSOR_ARCHITECTURE_AMD64
        CoreLast = CoreLast64
      EndIf
      Auslastung$ + "Core" + Str(i) + " = " + StrD(CoreLast, 2) + "%" + Space(20)
      If PeekL(Buffer + (4 * AnzCore) + (i << 2)) > #PDH_CSTATUS_NEW_DATA ;s.o.
        A = -1                                   ;war kein gültiger Wert
        Break
      EndIf     
    Next
    If A <> -1
      Debug Auslastung$
    EndIf
    Delay(1000)
  ForEver
 
  CloseQuery(hQuery)
  CloseLibrary(0)
EndIf
Have fun!
Helle

Re: CPU Usage Multi-core

Posted: Tue Oct 09, 2012 10:07 am
by doctorized
Helle wrote:Aua, my youth :mrgreen: !
Check this (my German version):
Your code is not working for me on Win 7 greek x64 for PB 4.61 x86 and x64.
Error message "Aufruf von PdhVbAddCounter fur Core"+ Str(i) + " fehlgeschlagen!" for every core of my cpu.
After this 0.00% is shown for every core on every loop.
I need the greek phrases for P1$ and P2$? I think you can take them somehow programmatically. If I find it I'll post it.

Re: CPU Usage Multi-core

Posted: Tue Oct 09, 2012 10:13 am
by ts-soft
Works only as 64-Bit program.

Re: CPU Usage Multi-core

Posted: Tue Oct 09, 2012 11:12 am
by Helle
Sorry, see new.
My problem: No 32-Bit-OS for tests (in VM only 1 Core; but... my mistake).
Yes, P1$ and P2$ are language-sensitive!
Gruss
Helle

Re: CPU Usage Multi-core

Posted: Tue Oct 09, 2012 3:15 pm
by doctorized
Helle wrote:Sorry, see new.
My problem: No 32-Bit-OS for tests (in VM only 1 Core; but... my mistake).
Yes, P1$ and P2$ are language-sensitive!
Gruss
Helle
Use this:

Code: Select all

#COUNTERPERF_PROCESSOR = 238
#COUNTERPERF_PERCENTPROCESSORTIME = 6

Procedure.s GetCPUCounter(strInstance.s)
    ; get Object & Counter names for CPU Usage
    ; Different languages of windows use different names so we use a look-up!
	If OpenLibrary(0, "pdh.dll")  
		*F = GetFunction(0, "PdhLookupPerfNameByIndexA")
		If *F
			 NameLen.l: ObjectName.s: CounterName.s
		    
		    NameLen = #MAX_PATH
		    ObjectName = Space(NameLen)
		    i = CallFunctionFast(*F,#Null, #COUNTERPERF_PROCESSOR, @ObjectName, @NameLen)
       
		    NameLen = #MAX_PATH
		    CounterName = Space(NameLen)
		    
		    i = CallFunctionFast(*F,#Null, #COUNTERPERF_PERCENTPROCESSORTIME, @CounterName, @NameLen)
		    Debug "\" + ObjectName + "(" + strInstance + ")\" + CounterName
		    ProcedureReturn "\" + ObjectName + "(" + strInstance + ")\" + CounterName
		EndIf
		CloseLibrary(0)
	EndIf
EndProcedure
This is what I use in a code of mine.