aboutsummaryrefslogtreecommitdiff
path: root/files/fr/web/javascript/memory_management/index.md
diff options
context:
space:
mode:
Diffstat (limited to 'files/fr/web/javascript/memory_management/index.md')
-rw-r--r--files/fr/web/javascript/memory_management/index.md142
1 files changed, 74 insertions, 68 deletions
diff --git a/files/fr/web/javascript/memory_management/index.md b/files/fr/web/javascript/memory_management/index.md
index 1e42785cde..2f02a5edec 100644
--- a/files/fr/web/javascript/memory_management/index.md
+++ b/files/fr/web/javascript/memory_management/index.md
@@ -8,29 +8,28 @@ tags:
translation_of: Web/JavaScript/Memory_Management
original_slug: Web/JavaScript/Gestion_de_la_mémoire
---
-<div>{{JsSidebar("Advanced")}}</div>
+{{JsSidebar("Advanced")}}
-<p>Les langages de bas niveau, tels que C, possèdent des primitives permettant de gérer la mémoire : <code><a href="https://pubs.opengroup.org/onlinepubs/009695399/functions/malloc.html">malloc()</a></code> et <code><a href="https://en.wikipedia.org/wiki/C_dynamic_memory_allocation#Overview_of_functions">free()</a></code> par exemple. En revanche, lorsqu'on utilise JavaScript, la mémoire est allouée lors de la création des objets puis libérée « automatiquement » lorsque ceux-ci ne sont plus utilisés. Cette libération automatique est appelée <em>garbage collection </em>en anglais ou ramasse-miettes. Le fait que ce processus soit automatique est souvent source de confusion et donne parfois l'impression que JavaScript (ou d'autres langages de haut niveau) ne permet pas de gérer la mémoire : nous allons voir que ce n'est pas le cas.</p>
+Les langages de bas niveau, tels que C, possèdent des primitives permettant de gérer la mémoire : [`malloc()`](https://pubs.opengroup.org/onlinepubs/009695399/functions/malloc.html) et [`free()`](https://en.wikipedia.org/wiki/C_dynamic_memory_allocation#Overview_of_functions) par exemple. En revanche, lorsqu'on utilise JavaScript, la mémoire est allouée lors de la création des objets puis libérée « automatiquement » lorsque ceux-ci ne sont plus utilisés. Cette libération automatique est appelée _garbage collection_ en anglais ou ramasse-miettes. Le fait que ce processus soit automatique est souvent source de confusion et donne parfois l'impression que JavaScript (ou d'autres langages de haut niveau) ne permet pas de gérer la mémoire : nous allons voir que ce n'est pas le cas.
-<h2 id="Le_cycle_de_vie_de_la_mémoire">Le cycle de vie de la mémoire</h2>
+## Le cycle de vie de la mémoire
-<p>Quel que soit le langage de programmation, le cycle de vie de la mémoire ressemblera à :</p>
+Quel que soit le langage de programmation, le cycle de vie de la mémoire ressemblera à :
-<ol>
- <li>Allouer la mémoire dont on a besoin</li>
- <li>Utiliser cette mémoire allouée (lecture, écriture)</li>
- <li>Libérer la mémoire allouée lorsqu'on n'en a plus besoin</li>
-</ol>
+1. Allouer la mémoire dont on a besoin
+2. Utiliser cette mémoire allouée (lecture, écriture)
+3. Libérer la mémoire allouée lorsqu'on n'en a plus besoin
-<p>Le deuxième point est explicite, au niveau du code, pour tous les langages de programmation. Le premier et le troisième points sont explicites pour les langages de bas niveau mais souvent implicites pour les langages de haut niveau tels que JavaScript.</p>
+Le deuxième point est explicite, au niveau du code, pour tous les langages de programmation. Le premier et le troisième points sont explicites pour les langages de bas niveau mais souvent implicites pour les langages de haut niveau tels que JavaScript.
-<h3 id="Allocation_de_la_mémoire_en_JavaScript">Allocation de la mémoire en JavaScript</h3>
+### Allocation de la mémoire en JavaScript
-<h4 id="Initialisation_des_valeurs">Initialisation des valeurs</h4>
+#### Initialisation des valeurs
-<p>Afin de simplifier l'écriture de code, JavaScript alloue la mémoire lors de la déclaration des variables :</p>
+Afin de simplifier l'écriture de code, JavaScript alloue la mémoire lors de la déclaration des variables :
-<pre class="brush: js">// alloue de la mémoire pour un nombre
+```js
+// alloue de la mémoire pour un nombre
var n = 123;
// alloue de la mémoire pour une chaîne de caractères
var s = "azerty";
@@ -54,22 +53,24 @@ function f(a) {
unElement.addEventListener('click', function(){
unElement.style.backgroundColor = 'blue';
}, false);
-</pre>
+```
-<h4 id="Allocation_par_appels_de_fonctions">Allocation par appels de fonctions</h4>
+#### Allocation par appels de fonctions
-<p>Certains appels de fonctions entraînent l'allocation mémoire d'un objet.</p>
+Certains appels de fonctions entraînent l'allocation mémoire d'un objet.
-<pre class="brush: js">// Alloue la mémoire pour un objet date
+```js
+// Alloue la mémoire pour un objet date
var d = new Date();
// Alloue de la mémoire pour un objet représentant un élément du DOM
var e = document.createElement('div');
-</pre>
+```
-<p>Certaines méthodes allouent de la mémoire pour des nouveaux objets ou de nouvelles valeurs.</p>
+Certaines méthodes allouent de la mémoire pour des nouveaux objets ou de nouvelles valeurs.
-<pre class="brush: js">var s = "azerty";
+```js
+var s = "azerty";
var s2 = s.substr(0, 3); // s2 est une nouvelle chaîne de caractères
// Les chaînes étant immuables, JavaScript peut choisir
// de ne pas allouer de mémoire mais seulement
@@ -80,35 +81,36 @@ var a2 = ["génération", "nan nan"];
var a3 = a.concat(a2);
// nouveau tableau de 4 éléments
// (résultat de la concaténation de a et a2)
-</pre>
+```
-<h3 id="Utilisation_des_variables">Utilisation des variables</h3>
+### Utilisation des variables
-<p>Utiliser des variables revient à lire et écrire la mémoire allouée. Cela peut être effectué lorsqu'on lit ou modifie la valeur d'une variable ou d'une propriété d'un objet ou encore lorsqu'on passe un argument à une fonction.</p>
+Utiliser des variables revient à lire et écrire la mémoire allouée. Cela peut être effectué lorsqu'on lit ou modifie la valeur d'une variable ou d'une propriété d'un objet ou encore lorsqu'on passe un argument à une fonction.
-<h3 id="Libérer_la_mémoire_qui_n'est_plus_nécessaire">Libérer la mémoire qui n'est plus nécessaire</h3>
+### Libérer la mémoire qui n'est plus nécessaire
-<p>La plupart des problèmes concernant la gestion de la mémoire surviennent à cet endroit. Le plus difficile est de savoir « quand » la mémoire allouée n'est plus utilisée. Pour les langages « bas niveau », il faut donc que le développeur détermine quelle partie de la mémoire n'est plus utilisée à tel endroit du code et la libère.</p>
+La plupart des problèmes concernant la gestion de la mémoire surviennent à cet endroit. Le plus difficile est de savoir « quand » la mémoire allouée n'est plus utilisée. Pour les langages « bas niveau », il faut donc que le développeur détermine quelle partie de la mémoire n'est plus utilisée à tel endroit du code et la libère.
-<p>Les interpréteurs des langages de haut niveau intègrent un composant logiciel, appelé « ramasse-miettes » qui a pour but de surveiller l'utilisation de la mémoire afin de déterminer quand une partie de la mémoire allouée n'est plus utilisée afin de la libérer automatiquement. Ce procédé ne peut être qu'une approximation car savoir si tel ou tel fragment de mémoire est nécessaire est un problème <a href="https://fr.wikipedia.org/wiki/D%C3%A9cidabilit%C3%A9">indécidable</a> (autrement dit, ce problème ne peut être résolu par un algorithme).</p>
+Les interpréteurs des langages de haut niveau intègrent un composant logiciel, appelé « ramasse-miettes » qui a pour but de surveiller l'utilisation de la mémoire afin de déterminer quand une partie de la mémoire allouée n'est plus utilisée afin de la libérer automatiquement. Ce procédé ne peut être qu'une approximation car savoir si tel ou tel fragment de mémoire est nécessaire est un problème [indécidable](https://fr.wikipedia.org/wiki/D%C3%A9cidabilit%C3%A9) (autrement dit, ce problème ne peut être résolu par un algorithme).
-<h2 id="Le_ramasse-miettes_ou_garbage_collection">Le ramasse-miettes ou <em>garbage collection</em></h2>
+## Le ramasse-miettes ou _garbage collection_
-<p>Comme on vient de le voir, savoir si de la mémoire peut être libérée demeure un problème indécidable. Les ramasses-miettes ne sont donc que des solutions restreintes pour ce problème. La section qui suit détaille les notions importantes pour comprendre ce mécanisme, ainsi que ses limitations.</p>
+Comme on vient de le voir, savoir si de la mémoire peut être libérée demeure un problème indécidable. Les ramasses-miettes ne sont donc que des solutions restreintes pour ce problème. La section qui suit détaille les notions importantes pour comprendre ce mécanisme, ainsi que ses limitations.
-<h3 id="Références">Références</h3>
+### Références
-<p>Le concept principal utilisé par les algorithmes de ramasse-miettes est celui de <em>référence</em>. Dans ce contexte, un objet en référence un autre lorsqu'il a accès à lui (implicitement ou explicitement). Ainsi, un objet JavaScript référencera son <a href="/fr/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain">prototype</a> (référence implicite) et ses propriétés (référence explicite).</p>
+Le concept principal utilisé par les algorithmes de ramasse-miettes est celui de _référence_. Dans ce contexte, un objet en référence un autre lorsqu'il a accès à lui (implicitement ou explicitement). Ainsi, un objet JavaScript référencera son [prototype](/fr/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain) (référence implicite) et ses propriétés (référence explicite).
-<p>Dans ce contexte, la notion d'objet s'étend et dépasse celle utilisée pour décrire les objets JavaScript, elle contiendra notamment les portées de fonctions (ou la portée globale).</p>
+Dans ce contexte, la notion d'objet s'étend et dépasse celle utilisée pour décrire les objets JavaScript, elle contiendra notamment les portées de fonctions (ou la portée globale).
-<h3 id="Compter_les_références">Compter les références</h3>
+### Compter les références
-<p>L'algorithme le plus simple consiste à faire l'équivalence entre « un objet n'est plus nécessaire » et « un objet n'a pas d'objet le référençant ». Ainsi un objet peut être « ramassé » par le ramasse-miettes quand il n'y a plus de références pointant vers lui.</p>
+L'algorithme le plus simple consiste à faire l'équivalence entre « un objet n'est plus nécessaire » et « un objet n'a pas d'objet le référençant ». Ainsi un objet peut être « ramassé » par le ramasse-miettes quand il n'y a plus de références pointant vers lui.
-<h4 id="Exemple">Exemple</h4>
+#### Exemple
-<pre class="brush: js">var o = {
+```js
+var o = {
a: {
b: 2
}
@@ -135,13 +137,14 @@ o2 = "yo"; // L'objet 'o' ne possède plus de références vers lui
oa = null; // la propriété 'a' ne possède plus de références
// vers elle. L'objet peut être ramassé et la mémoire
// libérée.
-</pre>
+```
-<h4 id="Une_limitation_les_cycles">Une limitation : les cycles</h4>
+#### Une limitation : les cycles
-<p>Cet algorithme est limité car il ne peut pas gérer les cycles (exemple : A référence B et B référence A, ce qui forme un cycle). Avec les cycles, des objets pourraient très bien ne plus être nécessaires et cependant il serait impossible de les ramasser pour libérer la mémoire en utilisant l'algorithme précédent car chaque objet serait référencé au moins une fois et aucun ne pourrait être « ramassé ». Les références circulaires peuvent parfois entraîner des fuites mémoire.</p>
+Cet algorithme est limité car il ne peut pas gérer les cycles (exemple : A référence B et B référence A, ce qui forme un cycle). Avec les cycles, des objets pourraient très bien ne plus être nécessaires et cependant il serait impossible de les ramasser pour libérer la mémoire en utilisant l'algorithme précédent car chaque objet serait référencé au moins une fois et aucun ne pourrait être « ramassé ». Les références circulaires peuvent parfois entraîner des fuites mémoire.
-<pre class="brush: js">function f() {
+```js
+function f() {
var o = {};
var o2 = {};
o.a = o2; // o référence o2
@@ -151,58 +154,61 @@ oa = null; // la propriété 'a' ne possède plus de références
}
f();
-</pre>
+```
-<h4 id="Exemple_réel">Exemple réel</h4>
+#### Exemple réel
-<p>Les navigateurs Internet Explorer 6 et 7 utilisent cet algorithme pour gérer les objets du DOM. Certains codes peuvent donc entraîner des fuites de mémoires, en voici un exemple :</p>
+Les navigateurs Internet Explorer 6 et 7 utilisent cet algorithme pour gérer les objets du DOM. Certains codes peuvent donc entraîner des fuites de mémoires, en voici un exemple :
-<pre class="brush: js">var div;
+```js
+var div;
window.onload = function() {
div = document.getElementById("monElementDiv");
div.referenceCirculaire = div;
div.desDonnees = new Array(10000).join("*");
};
-</pre>
+```
-<p>Dans cet exemple, l'élément du DOM <code>monElementDiv</code> possède une référence circulaire vers lui-même via la propriété <code>referenceCirculaire</code>. Si la propriété n'est pas retirée ou modifiée de façon explicite, un ramasse-miettes qui compte les références aura toujours au moins une référence comptée, ce qui gardera l'élément DOM en mémoire et ce même s'il a été retiré de l'arbre du DOM. Si l'élément du DOM contient beaucoup de données (ce qui est illustré ici avec la propriétés <code>desDonnées</code>), la mémoire consommée par ces données ne sera jamais libérée.</p>
+Dans cet exemple, l'élément du DOM `monElementDiv` possède une référence circulaire vers lui-même via la propriété `referenceCirculaire`. Si la propriété n'est pas retirée ou modifiée de façon explicite, un ramasse-miettes qui compte les références aura toujours au moins une référence comptée, ce qui gardera l'élément DOM en mémoire et ce même s'il a été retiré de l'arbre du DOM. Si l'élément du DOM contient beaucoup de données (ce qui est illustré ici avec la propriétés `desDonnées`), la mémoire consommée par ces données ne sera jamais libérée.
-<h3 id="Algorithme_«_marquer_et_balayer_»_(mark-and-sweep)">Algorithme « marquer et balayer » (<em>mark-and-sweep</em>)</h3>
+### Algorithme « marquer et balayer » (_mark-and-sweep_)
-<p>Cet algorithme réduit la définition « un objet n'est plus nécessaire » à « un objet ne peut être atteint ».</p>
+Cet algorithme réduit la définition « un objet n'est plus nécessaire » à « un objet ne peut être atteint ».
-<p>L'utilisation de cet algorithme implique de savoir quels sont les objets racines (en JavaScript, la racine est l'objet global). De façon périodique, le ramasse-miettes commencera par ces racines, listera tous les objets référencés par ces racines, puis les objets référencés par eux etc. Le ramasse-miettes pourra ainsi construire une liste de tous les objets accessibles et collecter ceux qui ne sont plus accessibles.</p>
+L'utilisation de cet algorithme implique de savoir quels sont les objets racines (en JavaScript, la racine est l'objet global). De façon périodique, le ramasse-miettes commencera par ces racines, listera tous les objets référencés par ces racines, puis les objets référencés par eux etc. Le ramasse-miettes pourra ainsi construire une liste de tous les objets accessibles et collecter ceux qui ne sont plus accessibles.
-<p>Cet algorithme est meilleur que le précédent car la proposition « un objet possède 0 référence » implique « un objet ne peut être atteint ». En revanche, la réciproque n'est pas vraie comme nous avons pu le voir avec les cycles.</p>
+Cet algorithme est meilleur que le précédent car la proposition « un objet possède 0 référence » implique « un objet ne peut être atteint ». En revanche, la réciproque n'est pas vraie comme nous avons pu le voir avec les cycles.
-<p>En 2012, l'ensemble des navigateurs web modernes disposent d'un ramasse-miettes implémentant cet algorithme <em>mark-and-sweep</em>. L'ensemble des améliorations apportées dans ce domaine de JavaScript représentent des améliorations basées sur cet algorithme, ce ne sont pas de nouveaux algorithmes ou une nouvelle définition pour les objets à supprimer.</p>
+En 2012, l'ensemble des navigateurs web modernes disposent d'un ramasse-miettes implémentant cet algorithme _mark-and-sweep_. L'ensemble des améliorations apportées dans ce domaine de JavaScript représentent des améliorations basées sur cet algorithme, ce ne sont pas de nouveaux algorithmes ou une nouvelle définition pour les objets à supprimer.
-<h4 id="Les_cycles_ne_posent_plus_problème">Les cycles ne posent plus problème</h4>
+#### Les cycles ne posent plus problème
-<p>Dans l'exemple ci-dessus, après le retour de la fonction, les deux objets ne sont plus référencés par quelque chose d'accessible depuis l'objet global. L'algorithme les marquera donc comme « non-accessibles ».</p>
+Dans l'exemple ci-dessus, après le retour de la fonction, les deux objets ne sont plus référencés par quelque chose d'accessible depuis l'objet global. L'algorithme les marquera donc comme « non-accessibles ».
-<h4 id="Limitation_libérer_la_mémoire_manuellement">Limitation : libérer la mémoire manuellement</h4>
+#### Limitation : libérer la mémoire manuellement
-<p>On pourrait parfois avoir envie de décider quand libérer la mémoire. En 2019, il n'est pas possible de déclencher le ramasse miettes en JavaScript.</p>
+On pourrait parfois avoir envie de décider quand libérer la mémoire. En 2019, il n'est pas possible de déclencher le ramasse miettes en JavaScript.
-<h2 id="Node.js">Node.js</h2>
+## Node.js
-<p>Node.js propose certaines options et outils pour configurer et déboguer des problèmes mémoires. Ces fonctionnalités peuvent ne pas être disponibles dans les environnements navigateur.</p>
+Node.js propose certaines options et outils pour configurer et déboguer des problèmes mémoires. Ces fonctionnalités peuvent ne pas être disponibles dans les environnements navigateur.
-<h3 id="Options_d'exécution">Options d'exécution</h3>
+### Options d'exécution
-<p>La quantité de mémoire pour la mémoire du tas (<em>heap</em>) peut être augmentée avec une option :</p>
+La quantité de mémoire pour la mémoire du tas (_heap_) peut être augmentée avec une option :
-<pre class="brush: bash">node --max-old-space-size=6000 index.js</pre>
+```bash
+node --max-old-space-size=6000 index.js
+```
-<p>On peut également exposer le ramasse-miettes afin de déboguer des problèmes mémoires. Cela s'active via une option et s'utilise avec le débogueur Chrome :</p>
+On peut également exposer le ramasse-miettes afin de déboguer des problèmes mémoires. Cela s'active via une option et s'utilise avec le débogueur Chrome :
-<pre class="brush: bash">node --expose-gc --inspect index.js</pre>
+```bash
+node --expose-gc --inspect index.js
+```
-<h2 id="Voir_aussi">Voir aussi</h2>
+## Voir aussi
-<ul>
- <li><a class="external" href="https://www.ibm.com/developerworks/web/library/wa-memleak/">Article d'IBM sur les pratiques menant aux fuites mémoires en JavaScript (2007)</a> (en anglais)</li>
- <li><a class="external" href="https://msdn.microsoft.com/en-us/magazine/ff728624.aspx">Billet de Kangax sur les méthodes à utiliser pour enregistrer les gestionnaires d'événements et éviter les fuites mémoires (2010)</a> (en anglais)</li>
- <li><a href="/fr/docs/Performance">La performance pour les logiciels Mozilla et les modules complémentaires</a></li>
-</ul>
+- [Article d'IBM sur les pratiques menant aux fuites mémoires en JavaScript (2007)](https://www.ibm.com/developerworks/web/library/wa-memleak/) (en anglais)
+- [Billet de Kangax sur les méthodes à utiliser pour enregistrer les gestionnaires d'événements et éviter les fuites mémoires (2010)](https://msdn.microsoft.com/en-us/magazine/ff728624.aspx) (en anglais)
+- [La performance pour les logiciels Mozilla et les modules complémentaires](/fr/docs/Performance)