Page 1 sur 3

CPUUsage Multi-processeur

Publié : sam. 19/janv./2008 1:49
par Gillou
Bonjour à tous,

Ce code est un début de projet pour l'évolution de l'un de mes progs, il a pour but de vous donner le pourcentage CPU utilisé par le système pour chaque processeur ou coeur.

Pourriez-vous me dire si ce code fonctionne sur votre ordi, en m'indiquant votre version de Windows

MERCI D'AVANCE !!!
   Structure SYSTEM_BASIC_INFORMATION
    reserved.l
    TimerResolution.l
    PageSize.l
    NumberOfPhysicalPages.l
    LowestPhysicalPageNumber.l
    HighestPhysicalPageNumber.l
    AllocationGranularity.l
    MinimumUserModeAddress.l
    MaximumUserModeAddress.l
    ActiveProcessorsAffinityMask.l
    NumberOfProcessors.l
EndStructure

Structure SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
    IdleTime.q
    KernelTime.q
    UserTime.q
    Reserved1.q[3]
EndStructure

#SystemBasicInformation = 0
#SystemProcessorPerformanceInformation = 8
#SysProcPerfInfoLength = 48

#PROCESS_QUERY_INFORMATION = $400
#HUNDRED_NANOSEC = 10000000

DeclareDLL.l GetNumberOfProcessor()

Global Frequency.q, TimeStart.q

Global NumberOfProcessors = GetNumberOfProcessor()

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 KernelTimesStop.d(NumberOfProcessors+1)
Global Dim UserTimesStop.d(NumberOfProcessors+1)
Global Dim IdleTimesStop.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)

ProcedureDLL.l GetNumberOfProcessor() ; Retourne le nombre de processeur
    Protected resultat, Lib, SBI.SYSTEM_BASIC_INFORMATION
    Lib = OpenLibrary ( #PB_Any , "ntdll.dll" )
     If Lib
         If CallFunction (Lib, "NtQuerySystemInformation" , #SystemBasicInformation , @SBI, SizeOf (SYSTEM_BASIC_INFORMATION), 0) = 0
            resultat = SBI\NumberOfProcessors
         EndIf
         CloseLibrary (Lib)
     EndIf
     ProcedureReturn resultat
EndProcedure

Procedure.d Div10k(Value.q)
     ProcedureReturn Value/10000
EndProcedure

Procedure GetProcessorsTimes(start = #True )
    Protected Lib
    Lib = OpenLibrary ( #PB_Any , "ntdll.dll" )
     If Lib
         If CallFunction (Lib, "NtQuerySystemInformation" , #SystemProcessorPerformanceInformation , @CpuInfo(), #SysProcPerfInfoLength * NumberOfProcessors, 0) = 0
             If start = #True
                KernelTimesStart(NumberOfProcessors) = 0
                IdleTimesStart(NumberOfProcessors) = 0
                UserTimesStart(NumberOfProcessors) = 0
                 For i = 0 To NumberOfProcessors - 1
                    KernelTimesStart(i) = Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStart(i) = Div10k(CpuInfo(i)\IdleTime)
                    UserTimesStart(i) = Div10k(CpuInfo(i)\UserTime)
                    KernelTimesStart(NumberOfProcessors) = KernelTimesStart(NumberOfProcessors) + Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStart(NumberOfProcessors) = IdleTimesStart(NumberOfProcessors) + Div10k(CpuInfo(i)\IdleTime)
                    UserTimesStart(NumberOfProcessors) = UserTimesStart(NumberOfProcessors) + Div10k(CpuInfo(i)\UserTime)
                 Next
             Else
                KernelTimesStop(NumberOfProcessors) = 0
                IdleTimesStop(NumberOfProcessors) = 0
                UserTimesStop(NumberOfProcessors) = 0
                 For i = 0 To NumberOfProcessors - 1
                    KernelTimesStop(i) = Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStop(i) = Div10k(CpuInfo(i)\IdleTime)
                    UserTimesStop(i) = Div10k(CpuInfo(i)\UserTime)
                    KernelTimesStop(NumberOfProcessors) = KernelTimesStop(NumberOfProcessors) + Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStop(NumberOfProcessors) = IdleTimesStop(NumberOfProcessors) +Div10k( CpuInfo(i)\IdleTime)
                    UserTimesStop(NumberOfProcessors) = UserTimesStop(NumberOfProcessors) + Div10k(CpuInfo(i)\UserTime)
                 Next
             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) * 10000 : 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 : CpuUsages(i) = 100 : EndIf
        CpuUsages(i) = CpuUsages(i) * NumberOfProcessors
        CpuUsages(NumberOfProcessors) = CpuUsages(NumberOfProcessors) + CpuUsages(i)
        KernelTimesStart(i) = KernelTimesStop(i)
        UserTimesStart(i) = UserTimesStop(i)
        IdleTimesStart(i) = IdleTimesStop(i)
         SetGadgetItemText (1, i, StrD (CpuUsages(i), 3), 1)
         SetGadgetItemText (1, i, StrD (KernelTimesStart(i), 3), 2)
         SetGadgetItemText (1, i, StrD (UserTimesStart(i), 3), 3)
         SetGadgetItemText (1, i, StrD (IdleTimesStart(i), 3), 4)
     Next
    
    KernelTimesStart(NumberOfProcessors) = KernelTimesStop(NumberOfProcessors)
    UserTimesStart(NumberOfProcessors) = UserTimesStop(NumberOfProcessors)
    IdleTimesStart(NumberOfProcessors) = IdleTimesStop(NumberOfProcessors)
    
    CpuUsages(NumberOfProcessors) = CpuUsages(NumberOfProcessors) / NumberOfProcessors
    
     SetGadgetItemText (1, NumberOfProcessors, StrD (CpuUsages(NumberOfProcessors), 3), 1)
     SetGadgetItemText (1, NumberOfProcessors, StrD (KernelTimesStart(NumberOfProcessors), 3), 2)
     SetGadgetItemText (1, NumberOfProcessors, StrD (UserTimesStart(NumberOfProcessors), 3), 3)
     SetGadgetItemText (1, NumberOfProcessors, StrD (IdleTimesStart(NumberOfProcessors), 3), 4)
    
    TimeStart = CurTime
EndProcedure

QueryPerformanceFrequency_ (@Frequency)
QueryPerformanceCounter_ (@TimeStart)

GetProcessorsTimes()

Win = OpenWindow ( #PB_Any , 0, 0, 535, 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, 515, 120, "CPU" , 75)
     AddGadgetColumn (1, 1, "% Usage" , 60)
     AddGadgetColumn (1, 2, "Kernel Time" , 120)
     AddGadgetColumn (1, 3, "User Time" , 120)
     AddGadgetColumn (1, 4, "Idle Time" , 120)
    
     For i=0 To NumberOfProcessors-1
         AddGadgetItem (1, -1, "CPU " + Str (i))
     Next
     AddGadgetItem (1, 2, "CPU TOTAL" )
    
     SetTimer_ ( WindowID (Win), 1, 1000, @refresh())
     Repeat
         Select WaitWindowEvent ()
             Case #PB_Event_Gadget
                 Select EventGadget ()
                     ;Case
                 EndSelect
             Case #PB_Event_CloseWindow
                Quit = 1
         EndSelect
     Until Quit = 1
     KillTimer_ ( WindowID (Win), 1)
EndIf

Publié : sam. 19/janv./2008 2:23
par venom
salut Gillou ,

j'ai un dual core chez moi et sa fonctionne niquel :wink: .
mais il me semble que dobro avait deja fait un truck comme sa non ?
ou je me trompe de personne :oops: .


@++

Publié : sam. 19/janv./2008 2:44
par Gillou
Arf, comme quoi j'aurais mieux fait de chercher avant (au moins je perds pas la main...)

en tout cas merci du test

;)

Publié : sam. 19/janv./2008 12:26
par Backup
venom a écrit :salut Gillou ,

j'ai un dual core chez moi et sa fonctionne niquel :wink: .
mais il me semble que dobro avait deja fait un truck comme sa non ?
ou je me trompe de personne :oops: .


@++
non j'ai repris un truc de Cpl Bator, qui te donne le nombre de Core dispo

et possiblement donne la possibilité d'utiliser l'un ou l'autre Core (mais je peux pas debugger n'ayant pas de multi core !!)

le prg de Gillou est complementaire , puisqu'il apporte plus d'informations :)

Publié : sam. 19/janv./2008 12:31
par venom
a oui exacte autant pour moi :wink: .


@++

Publié : sam. 19/janv./2008 22:11
par Droopy
Semble fonctionner sur mon core 2 duo 4300

Publié : dim. 20/janv./2008 0:06
par Gillou
Voila ce qui se passe quand on ne prend plus le temps de venir sur le fofo, on rate plein de truc super,...
je viens de regarder ton code Dobro et effectivement ça va me servir, un boulot de moins... :D

Et Merci de vos tests à tous!

Publié : dim. 20/janv./2008 0:44
par Ar-S
Marche impec sur mon A64 X2 4200+

Publié : dim. 20/janv./2008 1:01
par Backup
Gillou a écrit :Voila ce qui se passe quand on ne prend plus le temps de venir sur le fofo, on rate plein de truc super,...
je viens de regarder ton code Dobro et effectivement ça va me servir, un boulot de moins... :D

Et Merci de vos tests à tous!
attention pas pu tester, faute de Multicore chez moi :)

Publié : dim. 20/janv./2008 2:05
par Gillou
@Dobro, Ok pas de problèmes, je viens de tester et en effet quelques corrections à revoir mais déjà, il y a une base d'où partir déjà excellent

@Ar-s, Merci pour le test

Pour ceux qui on testé, d'après ce que j'ai compris vous avez tous des doubles coeurs (sous XP supposé?)

Personne avec un simple coeur ou un quadri ou plus?

Publié : dim. 20/janv./2008 10:07
par tmyke
Voici mon test avec un QuadCore, et Vista:

Image

Donc je dirais appriori que c'est pas très clair ;)
La fenetre du dessous est un mesh 3D qui tourne, pour pousser un des
coeur un petit peu (meme si une bonne part du boulot est fait par la carte video)

Publié : dim. 20/janv./2008 12:23
par Gillou
Effectivement, c'est pas terrible, gros bug dans l'affaire. Merci du test et de l'image :D

Et je me retrouve dans la situation de Dobro à essayer de trouver une panne et en corrigeant à l'aveuglette ;), au moins ça va me faire chercher

__________________


Correction du code, c'est loin de code final mais ça va m'aider à mieux cerner d'où vient l'erreur



Structure SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
    IdleTime.q
    KernelTime.q
    UserTime.q
    Reserved1.q[3]
EndStructure

#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 KernelTimesStop.d(NumberOfProcessors+1)
Global Dim UserTimesStop.d(NumberOfProcessors+1)
Global Dim IdleTimesStop.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() ; Retourne le nombre de processeur
    Protected SI.SYSTEM_INFO
     GetSystemInfo_ (@SI)
     ProcedureReturn SI\dwNumberOfProcessors
EndProcedure

Procedure.d Div10k(Value.q)
     If Value > #HUNDRED_NANOSEC
         ProcedureReturn Value/10000
     Else
         ProcedureReturn Value
     EndIf
EndProcedure

Procedure GetProcessorsTimes(start = #True )
    Protected Lib
    Lib = OpenLibrary ( #PB_Any , "ntdll.dll" )
     If Lib
         If CallFunction (Lib, "NtQuerySystemInformation" , #SystemProcessorPerformanceInformation , @CpuInfo(), #SysProcPerfInfoLength * NumberOfProcessors, 0) = 0
             If start = #True
                KernelTimesStart(NumberOfProcessors) = 0
                IdleTimesStart(NumberOfProcessors) = 0
                UserTimesStart(NumberOfProcessors) = 0
                 For i = 0 To NumberOfProcessors - 1
                    KernelTimesStart(i) = Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStart(i) = Div10k(CpuInfo(i)\IdleTime)
                    UserTimesStart(i) = Div10k(CpuInfo(i)\UserTime)
                    KernelTimesStart(NumberOfProcessors) = KernelTimesStart(NumberOfProcessors) + Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStart(NumberOfProcessors) = IdleTimesStart(NumberOfProcessors) + Div10k(CpuInfo(i)\IdleTime)
                    UserTimesStart(NumberOfProcessors) = UserTimesStart(NumberOfProcessors) + Div10k(CpuInfo(i)\UserTime)
                 Next
             Else
                KernelTimesStop(NumberOfProcessors) = 0
                IdleTimesStop(NumberOfProcessors) = 0
                UserTimesStop(NumberOfProcessors) = 0
                 For i = 0 To NumberOfProcessors - 1
                    KernelTimesStop(i) = Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStop(i) = Div10k(CpuInfo(i)\IdleTime)
                    UserTimesStop(i) = Div10k(CpuInfo(i)\UserTime)
                    KernelTimesStop(NumberOfProcessors) = KernelTimesStop(NumberOfProcessors) + Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStop(NumberOfProcessors) = IdleTimesStop(NumberOfProcessors) +Div10k( CpuInfo(i)\IdleTime)
                    UserTimesStop(NumberOfProcessors) = UserTimesStop(NumberOfProcessors) + Div10k(CpuInfo(i)\UserTime)
                 Next
             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) * 10000 : 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 : CpuUsages(i) = 100 : EndIf
        CpuUsages(i) = CpuUsages(i) * NumberOfProcessors
        CpuUsages(NumberOfProcessors) = CpuUsages(NumberOfProcessors) + CpuUsages(i)
        KernelTimesStart(i) = KernelTimesStop(i)
        UserTimesStart(i) = UserTimesStop(i)
        IdleTimesStart(i) = IdleTimesStop(i)
         SetGadgetItemText (1, i, StrD (CpuUsages(i), 3), 1)
         SetGadgetItemText (1, i, StrD (KernelTimesStart(i), 3), 2)
         SetGadgetItemText (1, i, StrD (UserTimesStart(i), 3), 3)
         SetGadgetItemText (1, i, StrD (IdleTimesStart(i), 3), 4)
     Next
    
    KernelTimesStart(NumberOfProcessors) = KernelTimesStop(NumberOfProcessors)
    UserTimesStart(NumberOfProcessors) = UserTimesStop(NumberOfProcessors)
    IdleTimesStart(NumberOfProcessors) = IdleTimesStop(NumberOfProcessors)
    
    CpuUsages(NumberOfProcessors) = CpuUsages(NumberOfProcessors) / NumberOfProcessors
    
     SetGadgetItemText (1, NumberOfProcessors, StrD (CpuUsages(NumberOfProcessors), 3), 1)
     SetGadgetItemText (1, NumberOfProcessors, StrD (KernelTimesStart(NumberOfProcessors), 3), 2)
     SetGadgetItemText (1, NumberOfProcessors, StrD (UserTimesStart(NumberOfProcessors), 3), 3)
     SetGadgetItemText (1, NumberOfProcessors, StrD (IdleTimesStart(NumberOfProcessors), 3), 4)
    
    TimeStart = CurTime
EndProcedure

QueryPerformanceFrequency_ (@Frequency)
QueryPerformanceCounter_ (@TimeStart)

GetProcessorsTimes()

Win = OpenWindow ( #PB_Any , 0, 0, 535, 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, 515, 120, "CPU" , 75)
     AddGadgetColumn (1, 1, "% Usage" , 60)
     AddGadgetColumn (1, 2, "Kernel Time" , 120)
     AddGadgetColumn (1, 3, "User Time" , 120)
     AddGadgetColumn (1, 4, "Idle Time" , 120)
    
     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_Gadget
                 Select EventGadget ()
                     ;Case
                 EndSelect
             Case #PB_Event_CloseWindow
                Quit = 1
         EndSelect
     Until Quit = 1
     KillTimer_ ( WindowID (Win), 1)
EndIf

Publié : dim. 20/janv./2008 12:54
par Jacobus
Ca à l'air de fonctionner avec mon double coeur Pentium D820 et c'est très utile cet outil. Je trouve dommage par contre que les temps donnés ne soient pas lisibles au format hh:mm:ss voire ss:ms:ns
J'avais essayé mais sans succès pour ma fonction GetProcessusTime(pid.l) qui récupère le temps processeur d'une application par son id.
ici : http://www.purebasic.fr/french/viewtopic.php?t=7480

Si tu permet je vais tenter une approche graphique de ton code qui mérite qu'on s'y attarde :)

Publié : dim. 20/janv./2008 13:15
par Gillou
Pas de problème, tu peux en faire ce que tu veux, mon but final est de faire évoluer un CPU monitor que j'avais conçu il y a quelques années ne gérant à l'époque que du simple coeur.

Et effectivement je vais voir pour convertir au format minutes, secondes...

En tout cas ton code en lien est aussi très intéressant, je vais l'étudier

Publié : dim. 20/janv./2008 13:54
par tmyke
J'ai refais le test. J'ai à priori les mêmes résultats, si ce n'est le total qui est bien
en bas cette fois. :?