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
Significant CPU used
Re: Significant CPU used
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:
WaitWindowEvent() – minimal CPU usage:
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
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
Re: Significant CPU used
Thanks Yuki,
I understood your explanation but I don't know how to modify my program loop (code of the main loop below)
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
-
- Enthusiast
- Posts: 125
- Joined: Wed May 20, 2020 5:19 pm
- Location: The 3rd planet in the Solar System
- Contact:
Re: Significant CPU used
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.
Macbook Air M2, PB 6.03Arm64 and x64.
Windows 10, PB 6.03 x64 and x86.
Re: Significant CPU used
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.
Re: Significant CPU used
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.
Re: Significant CPU used
Hello BarryG,
Thanks but I had removed the Delay(1) when I put WaitWindowEvent()
Thanks but I had removed the Delay(1) when I put WaitWindowEvent()