Code-Garage #59 - Comment fonctionne un "garbage collector" en programmation ?

Durée: 8m38s

Date de sortie: 09/05/2023

Les langages comme le JavaScript, le Java, le C# et bien d'autres gèrent la libération de la mémoire grâce à un mécanisme appelé le "ramasse-miettes", ou "garbage-collector" en anglais !

Notes de l'épisode :

Salut et bienvenue dans ce nouvel épisode du podcast de Code Garage,
je m'appelle Nicolas Brandin-Bernard et aujourd'hui on va parler de ce qui est le
garbage collector et comment est-ce qu'il fonctionne, plus particulièrement en
JavaScript mais on va aussi aborder d'autres langages et globalement le
fonctionnement. Alors le garbage collector qu'on appelle parfois GC ou DC en
anglais, en français ça se traduit littéralement par ramassemiette ou ramasseordure
mais on utilise plutôt le terme ramassemiette, ça désigne tout simplement un
processus automatisé dont le but est de libérer la mémoire dynamique qu'on
appelle aussi la hip qui est inutilisée par un programme au fur et à mesure de
son exécution. Alors si jamais les concepts de primitives, références,
mémoire dynamique et tout ça vous sont pas vraiment familiers, je vous mets en
lien dans les notes de l'épisode un article publié sur le site de Code Garage
où vous pourrez simplement apprendre et découvrir un peu tous ces concepts.
Dans les langages banniveaux comme le C par exemple il est possible de gérer la
mémoire dynamique de manière manuelle en trois phases, on va allouer un espace
mémoire avec des fonctions qui s'appellent maloc, caloc etc. On va
l'utiliser, on va initialiser une variable, écrire, la lire etc. Et puis on
va libérer la mémoire qu'on utilise plus avec la méthode free par exemple.
Mais en jarae script par exemple quand vous créez une référence vers un
nouvel objet, chaque allocation mémoire est faite de manière automatique donc
vous n'avez pas à savoir combien docte, vous avez besoin de réquisitionner
parce que vous allez en avoir besoin etc. Gérer tout ça à la main c'est pas
possible et vous n'avez pas non plus besoin de libérer la mémoire dynamique
qui est utilisée parce que c'est le moteur de jarae script qui s'en charge
grâce à son garbage collector. Donc ça c'est valable pour tous les langages
qui utilisent un garbage collector, tous les langages ne le font pas mais c'est le
cas de Java, de C sharp et de plein d'autres. Alors petite chose à noter aussi,
je parle de la mémoire dynamique où il faut effectivement créer, allouer,
désallouer etc. Mais je parle pas de la mémoire statique parce qu'en fait les
objets primitifs donc un entier, une string c'est un peu particulier mais en général
un entier, un boulet etc. Ce sont des objets primitifs qui sont
justement stockés dans la mémoire statique et ces objets là ils sont effacés dès que
vous sortez de la scope dans laquelle ils ont été créés. Donc si vous les
utilisiez dans une fonction, dès que vous allez sortir de cette
fonction ils vont être automatiquement détruits ce qui n'est pas le cas des
références et justement de la mémoire dynamique. Alors quel est la
problématique exactement ? Parce qu'avant de se pencher sur la solution
il faut bien comprendre le problème. Prenons par exemple une
zone mémoire qu'on va appeler M1 et qui prend 200 kilos octets de
place dans la mémoire dynamique et vers laquelle pointe trois références à
différents endroits de notre programme. Pour que notre programme ne soit pas
trop gourmand en mémoire, il va falloir qu'on puisse libérer l'énorme place
prise dès que cette zone mémoire ne sera plus utilisé. Le problème c'est que le
moteur JavaScript seul il ne peut pas prévoir en avance à quel moment de
l'exécution de notre programme cette zone mémoire ne sera plus pointée par
aucune référence. C'est pourquoi on a besoin d'un garbell
du collector dont le travail va être de découvrir les cases mémoires qui ne
sont plus référencés afin de les libérer. Alors la première approche la
plus simple c'est ce qu'on appelle le reference counting. Donc il y a comme je
disais des garbage collector dans beaucoup de langages et la réalité c'est
que chacun de ces garbage collector implément un algorithme de détection
différent parfois plus ou moins efficace. Alors la première approche qui a été
utilisée historiquement c'est le reference counting donc le comptage
des références traduit littéralement. C'est un algorithme qui consiste tout
simplement à stocker pour chaque zone de la mémoire dynamique utilisée le
nombre de références qui pointent vers cette zone et puis d'incrémenter ce
chiffre à chaque nouvelle référence ou de le décrémenter à chaque suppression
d'une référence. Quand le nombre de références tombe à zéro et bas c'est
qu'il est temps de libérer cette zone de la mémoire. Alors cette approche
marche et est fonctionnelle mais elle pose quelques problèmes dont deux
principaux c'est que le garbage collector il est en activité quasi
constante parfois pour libérer une seule petite zone mémoire de quelques octets
et ça perd donc de l'efficacité. Et également l'algorithme il est
incapable de libérer les zones mémoires qui sont pointées par des références
circulaires. Une référence circulaire c'est par exemple quand un objet se
référence lui-même ou lorsque deux objets contiennent
chacune ou chacun une référence vers de l'un vers l'autre donc par exemple vous
avez votre objet A qui référence votre objet B et l'objet B qui référence l'objet A.
Ce qui veut dire que le nombre de références ne peut jamais tomber à
zéro et que la mémoire ne sera jamais libéré c'est ce qu'on appelle une fuite
de mémoire. Alors il existe beaucoup de types de fuite de mémoire différents
mais là en l'occurrence c'est une fuite de mémoire de type de référence
circulaire. Et pour pallier justement à ça, JavaScript
il implément à la place un autre algorithme qu'on appelle Mark and Sweep.
Alors JavaScript peu importe son environnement d'exécution que ce soit le
navigateur web ou Node.js, il met à disposition un objet racine auquel toutes les
variables et les fonctions de premier niveau sont rattachées. Ces objets dans le
navigateur c'est l'objet window et dans le Node.js c'est l'objet process.
Ça signifie que n'importe quel objet d'une application JavaScript doit rester
accessible en remontant depuis l'objet racine jusqu'à l'objet en question en
traversant toutes les références nécessaires. Si on prend l'envers ça
veut dire que toute zone mémoire allouée par JavaScript mais non
atteignable depuis l'objet racine est en fait une zone qui peut être libérée.
L'algorithme de Mark and Sweep du Garage Collector, il consiste à flaguer donc à mettre
un petit drapeau pour surtout les objets inatteignables depuis la racine pour qu'il soit
tous collectés en même temps. Dès que JavaScript aura besoin de libérer de la
mémoire parce qu'il va commencer à en manquer ou parce qu'il va attendre, il va avoir atteint
un certain pourcentage de la mémoire. Cette approche est résout les deux problèmes
présentés juste avant dans l'approche de reference counting parce que une référence
circulaire comme les deux objets vont se référencer mais qui ne seront plus
rattachés à l'objet racine dès que ça va arriver on va pouvoir supprimer
tout simplement cet objet et ne plus avoir cette fuite de mémoire et en plus
tout simplement comme le Mark and Sweep il ne s'exécute pas dès qu'on supprime
une référence mais à un certain pourcentage de mémoire ou à un certain intervalle
et bien même si c'est des petites zones mémoires ça ne va pas prendre de puissance
au processeur d'aller libérer cette mémoire. Par contre il y a quand même un petit défaut
entre guillemets ou en tout cas une contrainte c'est que le passage du Garage Collector avec
cet algorithme là il est imprévisible et donc son exécution peut introduire quelques
effets de bord comme le ralentissement de l'application à un moment t si jamais vraiment
il y a énormément de choses à supprimer d'un seul coup. Très honnêtement ça n'arrive quasiment
jamais mais quand on travaille sur des applications très très spécifiques ou très lourdes ou des
choses comme ça ça peut être des choses qu'il faut qu'il faut prendre en compte mais c'est
extrêmement peu de projets qui qui qui ont un problème avec ces effets de bord. J'espère que
vous en aurez appris un petit peu plus sur le concept de Garage Collector et les deux
algorithmes que je vous ai présentés aujourd'hui. Moi je vous donnerai rendez-vous la semaine prochaine
pour un prochain épisode du podcast ou directement sur code-garage.fr pour retrouver
tous nos articles de blog, tous nos podcasts et évidemment tous nos cours complets pour apprendre
des nouvelles techniques, des nouveaux concepts et continuer à vous former dans votre vie de
développeur ou développeuse. Alors à très vite sur Code Garage, salut !

Les infos glanées

Je suis une fonctionnalité encore en dévelopement

Signaler une erreur

Code-Garage

Découvrons ensemble des sujets passionnants autour du métier de dev et de la programmation en général !
Tags
Card title

Lien du podcast

[{'term': 'Technology', 'label': None, 'scheme': 'http://www.itunes.com/'}]

Go somewhere