Optimiser la consommation de mémoire

Sujets variés concernant le développement en PureBasic
Avatar de l’utilisateur
microdevweb
Messages : 1800
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Optimiser la consommation de mémoire

Message par microdevweb »

Bonjour à tous,

Je partage ici une petite expérience concernant la consommation de mémoire de vos projet. A la base le gros avantage de PureBasic est qu'il n'est vraiment pas gourmand et un exécutable ne consomme que quelques Mo.

Par contre certains oublis peuvent vite faire grimper la consommation surtout si il se trouve dans une boucle, et si votre Pc est performant vous risquer de ne pas vous en rendre compte tout de suite lord de vos testes qui sont généralement de courte durée.

Voici quelques oublis qui peuvent consommer pas mal de mémoire

Ne pas libérer une image

CTRL+ALT+DELTE pour ouvrir le gestionnaire de tache, compiler le code et observer la mémoire elle commence à 1.4 Mo et augmente de 0.1 Mo pratiquement toutes les seconde.
Note: ce code n'est évidement pas à faire pour afficher l'heure. Il sert juste à illustrer mon propos.

Code : Tout sélectionner

; Note: This code it's just a example which explain the memory lost with a specific case
; usually i don't make it don't worry
Enumeration 
  #MainForm
  #DayTime
EndEnumeration
Global gImage=CreateImage(#PB_Any,128,128)
Global gEvent
LoadFont(0,"Arial",22,#PB_Font_HighQuality|#PB_Font_Bold)
Procedure ShowTime()
  Protected x,y,Text.s
  ; This Procedure show the current time
  ; usually i do not create a new image, 
  ; it only for prove the lost of memory.
  gImage=CreateImage(#PB_Any,128,128)
  StartDrawing(ImageOutput(gImage))
  DrawingMode(#PB_2DDrawing_Default)
  ; Make image background
  Box(0,0,ImageWidth(gImage),ImageHeight(gImage),RGB(255, 0, 0))
  ; Center the text
  DrawingFont(FontID(0))
  DrawingMode(#PB_2DDrawing_Transparent)
  Text=FormatDate("%hh-%ii-%ss",Date())
  x=(ImageWidth(gImage)/2)-(TextWidth(Text)/2)
  y=(ImageHeight(gImage)/2)-(TextHeight(Text)/2)
  DrawText(x,y,Text,RGB(255, 255, 255))
  StopDrawing()
  SetGadgetState(#DayTime,ImageID(gImage))
  ; Here i forget to free the image
  ; FreeImage(gImage)
EndProcedure
; Open window
OpenWindow(#MainForm,0,0,128,128,"Day time",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
ImageGadget(#DayTime,0,0,128,128,ImageID(gImage))
ShowTime()
; Add timer for each second
AddWindowTimer(#MainForm,0,1000)
; Main Loop
Repeat
  gEvent=WaitWindowEvent()
  Select gEvent
    Case #PB_Event_Timer
      ShowTime()
  EndSelect
Until gEvent=#PB_Event_CloseWindow
End
Refaite le teste mais cette fois décommentez

Code : Tout sélectionner

FreeImage(gImage)
La mémoire restera sur 1,4

D'autre cas : ne pas fermer une base de données, ne pas libérer un fichier etc...

Pour conclure, je pense qu'il ne faut hésiter à ouvrir le gestionnaire de tache quand on teste ses projets et regarder si consommation de mémoire reste stable.

Et une bonne habitude consiste à consulter la doc, exemple si j'utilise loadXml je constate dans la doc qu'il existe FreeXml() et je ne doit donc pas oublier de l'utiliser après évidement ne plus avoir besoins du fichier en question.

On peut être induit en erreur avec #Pb_Any, car même si la variable est écrasée comme dans mon exemple elle ne reprend que l'adresse de l'image mais une nouvelle image est créée en mémoire à chaque fois.

Je ne doute pas que la plupart d'entre vous n'oublie pas ce genres de choses, j'adresse donc plutôt cette remarque au novices et même si je ne suis plus novice il m'arrive encore fréquemment de faire des erreurs.
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
Ar-S
Messages : 9477
Inscription : dim. 09/oct./2005 16:51
Contact :

Re: Optimiser la consommation de mémoire

Message par Ar-S »

Bonjour microdevweb,
En effet, même si les données sont normalement vidées lorsqu'on quitte le programme, il est important de gérer les commandes freexxxx() durant l'utilisation du soft.
Même si les PC d'aujourd'hui ont beaucoup de RAM, il n'est pas impossible de faire planter le programme ou le système à cause d'une boucle qui va faire monter et saturer la conso.
Ton exemple est très parlant. Juste un point, je pense que tu devrais le commenter en français sur ce forum.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Marc56
Messages : 2147
Inscription : sam. 08/févr./2014 15:19

Re: Optimiser la consommation de mémoire

Message par Marc56 »

Merci microdevweb pour ce rappel :)

Quelques remarques:
  • L'augmentation de la RAM vient aussi d'un défaut de conception :arrow: tu créé l'image au début ET que tu la re-créée à chaque itération
    (C'est peut-être voulu pour l'exemple, mais ça montre bien l'effet des variables Globales)

    Code : Tout sélectionner

    Global gImage=CreateImage(#PB_Any,128,128) ; <--- Création de l'image
    Global gEvent
    LoadFont(0,"Arial",22,#PB_Font_HighQuality|#PB_Font_Bold)
    
    Procedure ShowTime()
      Protected x,y,Text.s
      ; This Procedure show the current time
      ; usually i do not create a new image,
      ; it only for prove the lost of memory.
      gImage=CreateImage(#PB_Any,128,128); <---- Création de l'image derechef (SetGadetState() suffit)
    ...

    :idea: Avec ShowLibraryViewer() en cliquant sur rafraichir, on voit bien les images se multiplier.

    C'est aussi un des effets de #Pb_Any pour les ID de gadget, car avec une Enumération le même numéro est réutilisé et ne provoque pas d'augmentation de la RAM (CreateImage() invoqué plusieurs fois avec le même numéro ne provoque pas d'erreur)
    Exemple:

    Code : Tout sélectionner

    Enumeration
      #MainForm
      #DayTime
      #ImgClock
    EndEnumeration
    CreateImage(#ImgClock,128,128)
  • Le gestionnaire de tâche peut s'appeler à la souris: Clic droit sur la barre de tâche
  • :idea: D'une manière générale, quand c'est possible, travailler en procédure avec des variables Protected :arrow: Libération auto des ressources
:wink:
Avatar de l’utilisateur
JohnJohnsonSHERMAN
Messages : 648
Inscription : dim. 13/déc./2015 11:05
Localisation : Allez, cherche...
Contact :

Re: Optimiser la consommation de mémoire

Message par JohnJohnsonSHERMAN »

Merci c'est toujours un point sensible ca :) Je me rapelle que dans mon petit serveur web, je ne faisait aucun free, résultat au bout de quelques heures de test ou simplement de quelques gros fichiers requêtés, je me retrouvais avec une mémoire pleine à ras bord ^^ :lol:

Des fois je me demande s'il ne faudrait pas mettre un warning du genre "Attention, ressource non libérée", mais c'est vrai que ce serait assez difficile à implémenter...
"Le bug se situe entre la chaise et le clavier"
Votre expert national en bogage et segfaults.

CPU : AMD A8 Quad core - RAM 8Gb - HDD 2To
  • Windows 10 x64 - PB 5.61 x64
  • Linux Ubuntu 16.04 LTS x64 (dual boot) - PB pas encore réinstallé
Répondre