[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/fr/docs/Web/JavaScript/Guide/Memory_management [Back]  [Original]

Gestion de la mmoire - JavaScript | MDN

Cette page a t traduite partir de l'anglais par la communaut. Vous pouvez contribuer en rejoignant la communaut francophone sur MDN Web Docs.

View in English Always switch to English

Gestion de la mmoire

Les langages de bas niveau, tels que C, possdent des primitives permettant de grer la mmoire : malloc() et free() par exemple. En revanche, lorsqu'on utilise JavaScript, la mmoire est alloue lors de la cration des objets puis libre automatiquement lorsque ceux-ci ne sont plus utiliss. Cette libration automatique est appele 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 grer la mmoire : nous allons voir que ce n'est pas le cas.

Dans cet article

Le cycle de vie de la mmoire

Quel que soit le langage de programmation, le cycle de vie de la mmoire ressemblera :

  1. Allouer la mmoire dont on a besoin
  2. Utiliser cette mmoire alloue (lecture, criture)
  3. Librer la mmoire alloue lorsqu'on n'en a plus besoin

Le deuxime point est explicite, au niveau du code, pour tous les langages de programmation. Le premier et le troisime points sont explicites pour les langages de bas niveau mais souvent implicites pour les langages de haut niveau tels que JavaScript.

Allocation de la mmoire en JavaScript

Initialisation des valeurs

Afin de simplifier l'criture de code, JavaScript alloue la mmoire lors de la dclaration des variables :

js
// alloue de la mmoire pour un nombre
var n = 123;
// alloue de la mmoire pour une chane de caractres
var s = "azerty";

// alloue de la mmoire pour un objet et les valeurs qu'il contient
var o = {
  a: 1,
  b: null,
};

// alloue de la mmoire pour un tableau et les valeurs qu'il contient
var a = [1, null, "abra"];

// alloue de la mmoire pour une fonction
// une fonction est un objet qui peut tre appel
function f(a) {
  return a + 2;
}

// les expressions de fonction allouent aussi de la mmoire
unElement.addEventListener(
  "click",
  function () {
    unElement.style.backgroundColor = "blue";
  },
  false,
);

Allocation par appels de fonctions

Certains appels de fonctions entranent l'allocation mmoire d'un objet.

js
// Alloue la mmoire pour un objet date
var d = new Date();

// Alloue de la mmoire pour un objet reprsentant un lment du DOM
var e = document.createElement("div");

Certaines mthodes allouent de la mmoire pour des nouveaux objets ou de nouvelles valeurs.

js
var s = "azerty";
var s2 = s.substr(0, 3); // s2 est une nouvelle chane de caractres
// Les chanes tant immuables, JavaScript peut choisir
// de ne pas allouer de mmoire mais seulement
// de stocker l'intervalle [0, 3].

var a = ["ouais ouais", "nan nan"];
var a2 = ["gnration", "nan nan"];
var a3 = a.concat(a2);
// nouveau tableau de 4 lments
// (rsultat de la concatnation de a et a2)

Utilisation des variables

Utiliser des variables revient lire et crire la mmoire alloue. Cela peut tre effectu lorsqu'on lit ou modifie la valeur d'une variable ou d'une proprit d'un objet ou encore lorsqu'on passe un argument une fonction.

Librer la mmoire qui n'est plus ncessaire

La plupart des problmes concernant la gestion de la mmoire surviennent cet endroit. Le plus difficile est de savoir quand la mmoire alloue n'est plus utilise. Pour les langages bas niveau , il faut donc que le dveloppeur dtermine quelle partie de la mmoire n'est plus utilise tel endroit du code et la libre.

Les interprteurs des langages de haut niveau intgrent un composant logiciel, appel ramasse-miettes qui a pour but de surveiller l'utilisation de la mmoire afin de dterminer quand une partie de la mmoire alloue n'est plus utilise afin de la librer automatiquement. Ce procd ne peut tre qu'une approximation car savoir si tel ou tel fragment de mmoire est ncessaire est un problme indcidable (autrement dit, ce problme ne peut tre rsolu par un algorithme).

Le ramasse-miettes ou garbage collection

Comme on vient de le voir, savoir si de la mmoire peut tre libre demeure un problme indcidable. Les ramasses-miettes ne sont donc que des solutions restreintes pour ce problme. La section qui suit dtaille les notions importantes pour comprendre ce mcanisme, ainsi que ses limitations.

Rfrences

Le concept principal utilis par les algorithmes de ramasse-miettes est celui de rfrence. Dans ce contexte, un objet en rfrence un autre lorsqu'il a accs lui (implicitement ou explicitement). Ainsi, un objet JavaScript rfrencera son prototype (rfrence implicite) et ses proprits (rfrence explicite).

Dans ce contexte, la notion d'objet s'tend et dpasse celle utilise pour dcrire les objets JavaScript, elle contiendra notamment les portes de fonctions (ou la porte globale).

Compter les rfrences

L'algorithme le plus simple consiste faire l'quivalence entre un objet n'est plus ncessaire et un objet n'a pas d'objet le rfrenant . Ainsi un objet peut tre ramass par le ramasse-miettes quand il n'y a plus de rfrences pointant vers lui.

Exemple

js
var o = {
  a: {
    b: 2,
  },
};
// 2 objets sont crs. L'un est rfrenc par l'autre en tant que proprit.
// L'autre est rfrenc car assign  la variable 'o'.
// Aucun des deux ne peut tre ramass par le ramasse-miettes.

var o2 = o; // la variable 'o2' est le deuxime lment qui
// rfrence l'objet o
o = 1; // dsormais, l'objet qui tait dans 'o' possde
// une seule rfrence de o2 vers lui

var oa = o2.a; // rfrence la proprit 'a' de l'objet
// cet objet a donc 2 rfrences : une
// par une proprit, l'autre par la variable 'oa'

o2 = "yo"; // L'objet 'o' ne possde plus de rfrences vers lui
// Il peut tre ramass.
// Cependant sa proprit 'a' est toujours rfrenc.
// La mmoire ne peut donc pas tre libre.

oa = null; // la proprit 'a' ne possde plus de rfrences
// vers elle. L'objet peut tre ramass et la mmoire
// libre.

Une limitation : les cycles

Cet algorithme est limit car il ne peut pas grer les cycles (exemple : A rfrence B et B rfrence A, ce qui forme un cycle). Avec les cycles, des objets pourraient trs bien ne plus tre ncessaires et cependant il serait impossible de les ramasser pour librer la mmoire en utilisant l'algorithme prcdent car chaque objet serait rfrenc au moins une fois et aucun ne pourrait tre ramass . Les rfrences circulaires peuvent parfois entraner des fuites mmoire.

js
function f() {
  var o = {};
  var o2 = {};
  o.a = o2; // o rfrence o2
  o2.a = o; // o2 rfrence o

  return "azerty";
}

f();

Exemple rel

Les navigateurs Internet Explorer 6 et 7 utilisent cet algorithme pour grer les objets du DOM. Certains codes peuvent donc entraner des fuites de mmoires, en voici un exemple :

js
var div;
window.onload = function () {
  div = document.getElementById("monElementDiv");
  div.referenceCirculaire = div;
  div.desDonnees = new Array(10000).join("*");
};

Dans cet exemple, l'lment du DOM monElementDiv possde une rfrence circulaire vers lui-mme via la proprit referenceCirculaire. Si la proprit n'est pas retire ou modifie de faon explicite, un ramasse-miettes qui compte les rfrences aura toujours au moins une rfrence compte, ce qui gardera l'lment DOM en mmoire et ce mme s'il a t retir de l'arbre du DOM. Si l'lment du DOM contient beaucoup de donnes (ce qui est illustr ici avec la proprits desDonnes), la mmoire consomme par ces donnes ne sera jamais libre.

Algorithme marquer et balayer (mark-and-sweep)

Cet algorithme rduit la dfinition un objet n'est plus ncessaire un objet ne peut tre atteint .

L'utilisation de cet algorithme implique de savoir quels sont les objets racines (en JavaScript, la racine est l'objet global). De faon priodique, le ramasse-miettes commencera par ces racines, listera tous les objets rfrencs par ces racines, puis les objets rfrencs par eux etc. Le ramasse-miettes pourra ainsi construire une liste de tous les objets accessibles et collecter ceux qui ne sont plus accessibles.

Cet algorithme est meilleur que le prcdent car la proposition un objet possde 0 rfrence implique un objet ne peut tre atteint . En revanche, la rciproque n'est pas vraie comme nous avons pu le voir avec les cycles.

En 2012, l'ensemble des navigateurs web modernes disposent d'un ramasse-miettes implmentant cet algorithme mark-and-sweep. L'ensemble des amliorations apportes dans ce domaine de JavaScript reprsentent des amliorations bases sur cet algorithme, ce ne sont pas de nouveaux algorithmes ou une nouvelle dfinition pour les objets supprimer.

Les cycles ne posent plus problme

Dans l'exemple ci-dessus, aprs le retour de la fonction, les deux objets ne sont plus rfrencs par quelque chose d'accessible depuis l'objet global. L'algorithme les marquera donc comme non-accessibles .

Limitation : librer la mmoire manuellement

On pourrait parfois avoir envie de dcider quand librer la mmoire. En 2019, il n'est pas possible de dclencher le ramasse miettes en JavaScript.

Node.js

Node.js propose certaines options et outils pour configurer et dboguer des problmes mmoires. Ces fonctionnalits peuvent ne pas tre disponibles dans les environnements navigateur.

Options d'excution

La quantit de mmoire pour la mmoire du tas (heap) peut tre augmente avec une option :

bash
node --max-old-space-size=6000 index.js

On peut galement exposer le ramasse-miettes afin de dboguer des problmes mmoires. Cela s'active via une option et s'utilise avec le dbogueur Chrome :

bash
node --expose-gc --inspect index.js

Voir aussi


Web Proxy Viewer  |  New URL  |  Original Page