Significant CPU used

Just starting out? Need help? Post your questions and find answers here.
jak64
Enthusiast
Enthusiast
Posts: 502
Joined: Sat Aug 15, 2020 5:02 pm
Location: Ciboure (France)

Significant CPU used

Post by jak64 »

Hello,
I wrote a program in Purebasic with a Windows window and several gadgets (buttons, lists, input area, etc).

When I run the program, the window is displayed and even if I do nothing, the program uses 25% of the CPU!

I added a "Delay(1)" instruction in the main loop and then the CPU used is 0%.

Can you explain to me why?

Isn't there another solution than to put "Delay(1)", for example an instruction that
I would put in the main loop and who would return control to the system?

thank you
User avatar
yuki
Enthusiast
Enthusiast
Posts: 101
Joined: Sat Mar 31, 2018 9:09 pm

Re: Significant CPU used

Post by yuki »

What does your event-loop look like ? It sounds like it's greedily/needlessly polling repeatedly, rather than more gracefully waiting for an event or similar before acting.

Are you by chance using WindowEvent() rather than WaitWindowEvent() ? The former checks for an event and immediately exits with 0 if there's nothing in the queue, while the latter will "suspend" until an event is ready. As a result, looping with WindowEvent() will max out a single thread's worth of CPU since it lacks the waiting/suspend mechanic to yield time to other tasks.

If you are using WaitWindowEvent() and still seeing the heavy usage described, it's possible (but unlikely) that something is sending an excessive number of messages to your application. It's also worth making sure the timeout parameter is greater than 0 (e.g., WaitWindowEvent(0) will cause heavy load and should be avoided).

To demonstrate this behaviour, compare the two samples below.

WindowEvent() – heavy CPU usage:

Code: Select all

Define wndMain = OpenWindow(#PB_Any, 0, 0, 400, 300, "test", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
Repeat
Until WindowEvent() = #PB_Event_CloseWindow
WaitWindowEvent() – minimal CPU usage:

Code: Select all

Define wndMain = OpenWindow(#PB_Any, 0, 0, 400, 300, "test", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
jak64
Enthusiast
Enthusiast
Posts: 502
Joined: Sat Aug 15, 2020 5:02 pm
Location: Ciboure (France)

Re: Significant CPU used

Post by jak64 »

Thanks Yuki,
I understood your explanation but I don't know how to modify my program loop (code of the main loop below)

Code: Select all

;---------- Boucle principale
Repeat
  AfficherTout=#False 
  If GetWindowState(#FenetreWindows)=#PB_Window_Normal      ; Si la fenêtre principale est affichée en taille normale
    If IsWindow(#FenetreJaquette)                           ; et que la fenêtre grande jaquette existe
      SetWindowState(#FenetreJaquette,#PB_Window_Normal)    ; alors la fenêtre grande jaquette doit être affichée en taille normale
    EndIf
  EndIf
  Event = WindowEvent()
  Select Event
      ;===== Changer le curseur lorsqu'un gadget est survolé
    Case #WM_MOUSEMOVE
      GetCursorPos_(@pt.POINT)
      hWind = WindowFromPoint_(PeekQ(@pt))
      If hWind = WindowID(#FenetreWindows) ; La souris est sur le fond de la fenêtre
        SetCursor_(mouse_normal)
      Else ; Mouse is over a gadget.
        SetCursor_(mouse_hand)
      EndIf
      ;===== Fermeture des fenêtres
    Case #PB_Event_CloseWindow
      Quitter=#True
      ;===== Empêcher le déplacement de la fenêtre (elle est recentrée automatiquement)
    Case #PB_Event_MoveWindow
      If GetWindowState(#FenetreWindows) = #PB_Window_Normal
        ResizeWindow(#FenetreWindows,XApplication,YApplication,LargeurApplication,HauteurApplication)
      EndIf
      ;===== Evènements sur les gadgets
    Case #PB_Event_Gadget
      Select EventGadget()
          
          ;===== Bouton pout lire la vidéo tutoriel
        Case #BoutonAide
          Select EventType()
            Case #PB_EventType_LeftClick
              LireVideoAide()
          EndSelect
          
          ;===== Bouton AFFICHER TOUS LES FILMS
        Case #TousLesFilms
          Select EventType()
            Case #PB_EventType_LeftClick
              HideGadget(#ComboGenres,#True)          ; Cacher le gadget ComboBox Genres
              HideGadget(#TitreSerie,#True)           ; Cacher le gadget Text titre série
              SetGadgetState(#ListeSeries, -1)        ; Désélectionner les séries
              HideGadget(#Recherche,#False)           ; Afficher la zone de saisie de Recherche
              HideGadget(#OptionTitre,#False)         ; Afficher le bouton radio Titre
              HideGadget(#OptionActeur,#False)        ; Afficher le bouton radio Acteur
              HideGadget(#OptionRealisateur,#False)   ; Afficher le bouton radio Réalisateur
              HideGadget(#OptionGenre,#False)         ; Afficher le bouton radio Genre
              SetGadgetText(#Recherche, "")           ; Effacer le contenu de la zone de recherche
              SetActiveGadget(#Recherche)             ; Mettre le curseur dans la zone de saisie de la recheche
              SetGadgetState(#OptionTitre, #True)     ; Cocher le bouton radio Titre
              SetGadgetState(#ChkFilms, #True)
              HideGadget(#ChkFilms, #False)
              HideGadget(#ChkSeries, #False)
              SetGadgetState(#ChkSeries, #True)
              HideGadget(#NbTotalFilms,#False)
              If CountGadgetItems(#ListeFilms)<>NbInitialVideos
                RechercheParTitre()                     ; Rechercher les films et les afficher dans la ListeFilms
              EndIf
              CacherGadgetsDetail()                   ; Cacher les gadgets détail
              AfficherTout=#True
          EndSelect
          
          ;===== Un film est cliqué dans la liste des films         
        Case #ListeFilms
          Select EventType()
            Case #PB_EventType_LeftDoubleClick ; Double clic gauche alors lecture du film
              Resultat=GetGadgetState(#ListeFilms)          ; Récuperer l'indice dans la liste
              If Resultat>-1
                LireFilm() ; lancer la lecture du film
              EndIf
            Case #PB_EventType_LeftClick ; Clic gauche, alors afficher détail du film
              
              If EventData() ; Pour détecter clic sur entêtes colonnes liste des films
                If EventData() = 1 ; Tri sur titre du film
                  TriFimsSurTitre()
                ElseIf EventData() = 2
                  TriFimsSurAnnee()
                EndIf 
                
              Else
                Resultat=GetGadgetState(#ListeFilms)          ; Récuperer l'indice dans la liste
                If Resultat>-1
                  IndiceFilm=TFilmsRecherches(Resultat)\IdFilm  ; Récupérer l'indice du film dans le tableau
                  AfficherDetailFilm()
                Else
                  CacherGadgetsDetail()
                EndIf
              EndIf
          EndSelect
          
          ;===== Le titre d'une série est cliqué  
        Case #ListeSeries
          Select EventType()
            Case #PB_EventType_LeftClick
              Resultat=GetGadgetState(#ListeSeries)
              If Resultat>-1
                HideGadget(#Recherche,#True)          ; Cacher la zone de saisie de recherche
                HideGadget(#OptionTitre,#True)        ; Cacher le bouton radio Titre
                HideGadget(#OptionActeur,#True)       ; Cacher le bouton radio Acteur
                HideGadget(#OptionRealisateur,#True)  ; Cacher le bouton radio Réalisateur
                HideGadget(#OptionGenre,#True)        ; Cacher le bouton radio Genre
                HideGadget(#ComboGenres,#True)        ; Cacher la ComboBox Genres
                HideGadget(#ChkFilms, #True)
                SetGadgetState(#ChkFilms, #True)
                HideGadget(#ChkSeries, #True)
                HideGadget(#NbTotalSeries,#True)
                SetGadgetState(#ChkSeries, #True)
                CacherGadgetsDetail()
                AfficherSerie()
              EndIf
          EndSelect
          
          ;===== La zone de recherche a été modifiée
        Case #Recherche
          Select EventType()
            Case #PB_EventType_Change
              CacherGadgetsDetail()                   ; Cacher les gadgets détails du film
              SetGadgetState(#ListeSeries,-1)         ; Désélectionner les séries
              If GetGadgetState(#OptionTitre)         ; Si bouton radio Titre coché
                RechercheParTitre()                   ; Rechercher sur le titre
              ElseIf GetGadgetState(#OptionActeur)    ; Si bouton radio Acteur coché
                RechercheParActeur()                  ; Rechercher sur le nom de l'acteur
              ElseIf GetGadgetState(#OptionRealisateur)    ; Si bouton radio Réalisateur coché
                RechercheParRealisateur()                  ; Rechercher sur le nom du réalisateur              
              ElseIf GetGadgetState(#OptionGenre)          ; Si bouton radio Genre coché
                RechercheParGenre()                        ; Rechercher par genre
              EndIf
          EndSelect
          
          ;===== Le bouton radio Titre est coché
        Case #OptionTitre
          SetGadgetState(#ComboGenres, -1)            ; Désélectionner ComboBox Genres
          HideGadget(#ComboGenres,#True)              ; Cacher la ComboBox Genres
          HideGadget(#Recherche,#False)               ; Afficher la zone Recherche
          If AfficherTout
            SetGadgetText(#Recherche, "")               ; Effacer la zone de saisie de Recherche
          EndIf
          SetGadgetState(#ChkFilms, #True)
          SetGadgetState(#ChkSeries, #True)
          SetActiveGadget(#Recherche)                 ; Mettre le curseur dans la zone de recherche
          CacherGadgetsDetail()                       ; Cacher les gadgets détail
          If CountGadgetItems(#ListeFilms)<>NbInitialVideos
            RechercheParTitre()                         ; Rechercher par Titre
          EndIf
          
          ;===== Le bouton radio Acteur est coché 
        Case #OptionActeur
          SetGadgetState(#ListeSeries,-1)             ; Désélectionner les séries
          SetGadgetState(#ComboGenres, -1)            ; Désélectionner ComboBox Genres
          HideGadget(#ComboGenres,#True)              ; Cacher la ComboBox Genres
          HideGadget(#Recherche,#False)               ; Afficher la zone Recherche
          SetGadgetState(#ChkFilms, #True)
          SetGadgetState(#ChkSeries, #True)
          If AfficherTout
            SetGadgetText(#Recherche, "")               ; Effacer la zone de saisie de Recherche
          EndIf
          SetActiveGadget(#Recherche)                 ; Mettre le curseur dans la zone de recherche
          CacherGadgetsDetail()                       ; Cacher les gadgets détail
          If CountGadgetItems(#ListeFilms)<>NbInitialVideos
            RechercheParActeur()                        ; Rechercher par Acteur
          EndIf
          
          ;===== Le bouton radio Réalisateur est coché 
        Case #OptionRealisateur
          SetGadgetState(#ListeSeries,-1)             ; Désélectionner les séries
          SetGadgetState(#ComboGenres, -1)            ; Désélectionner ComboBox Genres
          HideGadget(#ComboGenres,#True)              ; Cacher la ComboBox Genres
          HideGadget(#Recherche,#False)               ; Afficher la zone Recherche
          SetGadgetState(#ChkFilms, #True)
          SetGadgetState(#ChkSeries, #True)
          If AfficherTout
            SetGadgetText(#Recherche, "")               ; Effacer la zone de saisie de Recherche
          EndIf
          SetActiveGadget(#Recherche)                 ; Mettre le curseur dans la zone de recherche
          CacherGadgetsDetail()                       ; Cacher les gadgets détail
          If CountGadgetItems(#ListeFilms)<>NbInitialVideos
            RechercheParRealisateur()                   ; Rechercher par Réalisateur
          EndIf
          
          ;===== Le bouton radio Genre est coché (un module permet d'ouvrir automatiquement la ComboBox Genres)
        Case #OptionGenre
          SetGadgetState(#ListeSeries,-1)             ; Désélectionner les séries
          HideGadget(#ComboGenres,#False)             ; Afficher la ComboBox Genres
          SetGadgetState(#ComboGenres,-1)             ; Désélectionner les genres
          SetGadgetState(#ChkFilms, #True)
          SetGadgetState(#ChkSeries, #True)
          SetGadgetText(#Recherche, "")               ; Effacer la zone de saisie de Recherche
          HideGadget(#Recherche,#True)                ; Cacher la zone de saisie de recherche
          CacherGadgetsDetail()                       ; Cacher les gadgets détail
          If CountGadgetItems(#ListeFilms)<>NbInitialVideos
            RechercheParGenre()                         ; Afficher tous les titres de film
          EndIf
          
          ;===== Un genre a été cliqué dans la ComboBox Genres
        Case #ComboGenres
          Select EventType()
            Case #PB_EventType_Change
              SetActiveGadget(#Recherche)
              SetGadgetState(#ChkFilms, #True)
              SetGadgetState(#ChkSeries, #True)
              SetGadgetText(#Recherche,GetGadgetItemText(#ComboGenres, GetGadgetState(#ComboGenres))) ; La zone Recherche est valorisée
              RechercheParGenre()                                                                     ; La recherche est lancée
              HideGadget(#SelectionTitre,#False)
              CacherGadgetsDetail()
          EndSelect
          
          ;===== Clic sur case à cocher Film
        Case #ChkFilms
          Select EventType()
            Case #PB_EventType_LeftClick
              CaseACocherFilmsSeries()
          EndSelect
          
          ;===== Clic sur case à cocher Serie
        Case #ChkSeries
          Select EventType()
            Case #PB_EventType_LeftClick
              CaseACocherFilmsSeries()
          EndSelect
          
          ;===== Clic sur la petite jaquette
        Case #Jaquette
          Select EventType()
            Case #PB_EventType_LeftClick
              AfficherGrandeJaquette() ; La grande jaquette est affichée
          EndSelect
          
          ;===== Clic sur le nom du réalisateur
        Case #Realisateur
          Select EventType()
            Case #PB_EventType_LeftClick
              ClicSurRealisateur()
          EndSelect 
          
          ;===== Clic sur bouton pour lire le film
        Case #Lecture
          Select EventType()
            Case #PB_EventType_LeftClick
              LireFilm() ; lancer la lecture du film
          EndSelect 
          
      EndSelect
  EndSelect
  Delay(1)
Until Quitter
dibor
Enthusiast
Enthusiast
Posts: 125
Joined: Wed May 20, 2020 5:19 pm
Location: The 3rd planet in the Solar System
Contact:

Re: Significant CPU used

Post by dibor »

Put Event = WaitWindowEvent() instead Event = WindowEvent()
Mac Studio M1Max, PB 6.03Arm64 and x64.
Macbook Air M2, PB 6.03Arm64 and x64.
Windows 10, PB 6.03 x64 and x86.
jak64
Enthusiast
Enthusiast
Posts: 502
Joined: Sat Aug 15, 2020 5:02 pm
Location: Ciboure (France)

Re: Significant CPU used

Post by jak64 »

Thank you both, it's OK, the program no longer uses 25% of the CPU but 0%, I think it consumes a little bit anyway.
BarryG
Addict
Addict
Posts: 3324
Joined: Thu Apr 18, 2019 8:17 am

Re: Significant CPU used

Post by BarryG »

Also, you've got Delay(1) at the end - you don't need that when using WaitWindowEvent(), because it will make window events react slower.
jak64
Enthusiast
Enthusiast
Posts: 502
Joined: Sat Aug 15, 2020 5:02 pm
Location: Ciboure (France)

Re: Significant CPU used

Post by jak64 »

Hello BarryG,

Thanks but I had removed the Delay(1) when I put WaitWindowEvent()
Post Reply