Page 1 sur 1

Optimiser la consommation de mémoire

Publié : sam. 12/août/2017 8:48
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.

Re: Optimiser la consommation de mémoire

Publié : sam. 12/août/2017 9:58
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.

Re: Optimiser la consommation de mémoire

Publié : sam. 12/août/2017 10:22
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:

Re: Optimiser la consommation de mémoire

Publié : lun. 14/août/2017 11:05
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...