web-dev-qa-db-fra.com

Qu'est-ce que la récupération de mémoire JavaScript?

Qu'est-ce que la récupération de mémoire JavaScript? Qu'est-ce qui est important pour un programmeur Web pour comprendre la récupération de mémoire JavaScript afin d'écrire un meilleur code?

289
user290

Eric Lippert a écrit un billet de blog détaillé sur ce sujet il y a bien longtemps (en le comparant en outre à VBScript ). Plus précisément, il a écrit à propos de JScript , qui est la propre implémentation de ECMAScript par Microsoft, bien que très similaire à JavaScript. J'imagine que vous pouvez supposer que la grande majorité des comportements seraient les mêmes pour le moteur JavaScript d'Internet Explorer. Bien entendu, la mise en œuvre variera d’un navigateur à l’autre, même si je suppose que vous pourriez appliquer un certain nombre de principes communs à d’autres appli- cateurs.

Cité de cette page:

JScript utilise un collecteur de mémoire non générationnel. Cela fonctionne comme ceci:

  • Chaque variable qui est "dans la portée" est appelée "scavenger". Un nettoyeur peut faire référence à un nombre, un objet, une chaîne, peu importe. Nous maintenons une liste de scavengers - les variables sont déplacées dans la liste scav quand elles entrent dans la portée et hors de la liste scav quand elles sont hors de portée.

  • De temps en temps, le ramasse-miettes s'exécute. Tout d'abord, il met une "marque" sur chaque objet, variable, chaîne, etc. - toute la mémoire suivie par le GC. (JScript utilise la structure de données VARIANT en interne et cette structure contient de nombreux bits inutilisés, nous n'en avons donc choisi qu'un.)

  • Deuxièmement, cela efface la marque sur les récupérateurs et la fermeture transitive des références aux récupérateurs. Donc, si un objet Scavenger fait référence à un objet nonscavenger, nous effaçons les bits de celui-ci et de tout ce à quoi il fait référence. (J'utilise le mot "clôture" dans un sens différent de celui de mon précédent message.)

  • À ce stade, nous savons que toute la mémoire encore marquée est une mémoire allouée qui ne peut être atteinte par aucun chemin à partir d'une variable de l'étendue. Tous ces objets ont pour instruction de se démolir, ce qui détruit toute référence circulaire.

L'objectif principal de la récupération de place est de permettre au programmeur non de se soucier de la gestion de la mémoire des objets qu'il crée et utilise, bien que rien ne puisse l'éviter, bien sûr. C'est toujours avantageux. d'avoir au moins une idée approximative du fonctionnement de la collecte des ordures.

Il y a quelques points particuliers dont il faut être conscient. Le site de développeur Apple a des instructions en la matière. Deux importants à partir de là:

  • Utilisez les instructions de suppression. Chaque fois que vous créez un objet à l'aide d'une nouvelle instruction, associez-le à une instruction delete. Cela garantit que toute la mémoire associée à l'objet, y compris son nom de propriété, est disponible pour le garbage collection. L'instruction delete est décrite plus en détail dans "Libération d'objets".
  • Utilisez le mot clé var. Toute variable créée sans le mot clé var est créée au niveau global et n’est jamais éligible pour le garbage collection, ce qui présente l’occasion d’une fuite de mémoire.

J'imagine que les pratiques devraient s'appliquer à tous les moteurs JavaScript (dans différents navigateurs), mais comme il s'agit d'un site Apple, ils peuvent être quelque peu spécifiques. à Safari. (Peut-être que quelqu'un pourrait clarifier cela?)

J'espère que cela pourra aider.

190
Noldorin

Attention aux références circulaires lorsque des objets DOM sont impliqués:

Modèles de fuite de mémoire en JavaScript

N'oubliez pas que la mémoire ne peut être récupérée que s'il n'y a pas de référence active à l'objet. Il s’agit d’un écueil courant avec les fermetures et les gestionnaires d’événements, car certains moteurs JS ne vérifient pas les variables qui sont réellement référencées dans les fonctions internes et conservent toutes les variables locales des fonctions qui les entourent.

Voici un exemple simple:

function init() {
    var bigString = new Array(1000).join('xxx');
    var foo = document.getElementById('foo');
    foo.onclick = function() {
        // this might create a closure over `bigString`,
        // even if `bigString` isn't referenced anywhere!
    };
}

Une implémentation JS naïve ne peut pas collecter bigString tant que le gestionnaire d'événements est présent. Il existe plusieurs façons de résoudre ce problème, par exemple définir bigString = null à la fin de init() (delete ne fonctionnera pas pour les variables locales et les arguments de la fonction: delete supprime les propriétés des objets et la variable objet est inaccessible - ES5 en mode strict jettera même ReferenceError si vous essayez de supprimer une variable locale!).

Je recommande d'éviter autant que possible les fermetures inutiles si vous vous préoccupez de la consommation de mémoire.

52
Christoph

Bonne citation tirée d'un blog

Le composant DOM est "effacé", comme le composant JScript, ce qui signifie que si vous créez un objet dans l'un des composants, puis perdez la trace de cet objet, il sera éventuellement nettoyé.

Par exemple:

function makeABigObject() {
var bigArray = new Array(20000);
}

Lorsque vous appelez cette fonction, le composant JScript crée un objet (nommé bigArray) accessible dans la fonction. Cependant, dès que la fonction revient, vous "perdez la trace" de bigArray car il n'y a plus moyen de s'y référer. Eh bien, le composant JScript réalise que vous en avez perdu la trace et que bigArray est nettoyé - sa mémoire est récupérée. Le même genre de chose fonctionne dans le composant DOM. Si vous dites document.createElement('div'), ou quelque chose de similaire, le composant DOM crée un objet pour vous. Une fois que vous perdez la trace de cet objet d’une manière ou d’une autre, le composant DOM nettoie les objets associés.

15
TStamper

Autant que je sache, les objets JavaScript sont des ordures ramassées périodiquement lorsqu'il ne reste aucune référence à l'objet. C'est quelque chose qui se produit automatiquement, mais si vous voulez en savoir plus sur son fonctionnement, au niveau C++, il est judicieux de jeter un coup d'œil au WebKit ou le code source V8

En général, vous n'avez pas besoin d'y penser, mais dans les navigateurs plus anciens, comme IE 5.5 et les versions antérieures de IE 6, et peut-être dans les versions actuelles, les fermetures créeraient des références circulaires qui se termineraient up manger la mémoire. Dans le cas particulier que je veux dire à propos des fermetures, c'était lorsque vous avez ajouté une référence JavaScript à un objet dom et un objet à un objet DOM faisant référence à l'objet JavaScript. Fondamentalement, il ne pourrait jamais être collecté, et finirait par rendre le système d'exploitation instable dans les applications de test en boucle pour créer des pannes. En pratique, ces fuites sont généralement petites, mais pour garder votre code propre, vous devez supprimer la référence JavaScript à l'objet DOM.

En règle générale, il est judicieux d'utiliser le mot clé delete pour dé-référencer immédiatement les objets volumineux tels que les données JSON que vous avez reçus, et faites ce que vous souhaitez en faire, en particulier dans le développement Web mobile. Ainsi, le balayage suivant du CPG supprime cet objet et libère sa mémoire.

13
Heat Miser

la récupération de place (GC) est une forme de gestion automatique de la mémoire qui supprime les objets dont ils n’avaient plus besoin.

n'importe quel processus traiter avec la mémoire suivez ces étapes:

1 - allouez l’espace mémoire dont vous avez besoin

2 - faire du traitement

3 - libérer cet espace mémoire

deux principaux algorithmes sont utilisés pour détecter les objets dont vous n'avez plus besoin.

Récupération de données de comptage de références : cet algorithme réduit la définition de "un objet n'est plus nécessaire" à "un objet ne lui référant pas d'objet", l'objet sera supprimé si aucune référence ne le désigne

Algorithme Mark-and-sweep : connecte chaque objet à la source racine. aucun objet ne se connecte à la racine ou à un autre objet. cet objet sera supprimé.

actuellement les navigateurs les plus modernes utilisant le deuxième algorithme. 

6

"En informatique, le garbage collection (GC) est une forme de gestion automatique de la mémoire. Le garbage collector, ou tout simplement le collecteur, tente de récupérer les déchets ou la mémoire utilisée par des objets auxquels l'application ne procédera jamais à une mutation ou une mutation."

Tous les moteurs JavaScript ont leurs propres éboueurs et peuvent être différents. La plupart du temps, vous n'avez pas à vous en occuper, car ils ne font que ce qu'ils sont censés faire.

Écrire un meilleur code dépend principalement de votre connaissance des principes de programmation, du langage et de la mise en oeuvre.

4
mtasic85

Qu'est-ce que la récupération de mémoire JavaScript? 

vérifier this

Ce qui est important pour un programmeur Web pour comprendre la récupération de mémoire JavaScript, afin d'écrire un meilleur code?

En Javascript, vous ne vous souciez pas de l'allocation de mémoire ni de la désallocation. L'ensemble du problème est demandé à l'interprète Javascript. Les fuites sont toujours possibles en Javascript, mais ce sont des bogues de l'interprète. Si vous êtes intéressé par ce sujet, vous pouvez en lire plus dans www.memorymanagement.org

1
dfa

Sous Windows, vous pouvez utiliser Drip.exe pour rechercher des fuites de mémoire ou vérifier si votre routine de mém libre fonctionne. 

C'est très simple, il suffit d'entrer l'URL d'un site Web et vous verrez la consommation de mémoire du rendu intégré IE. Puis cliquez sur Actualiser. Si la mémoire augmente, vous avez trouvé une fuite de mémoire quelque part sur la page Web. Mais ceci est également très utile pour voir si les routines de libération de mémoire fonctionnent pour IE. 

1
powtac

Les types de référence ne stockent pas l’objet directement dans la variable à laquelle il est affecté. La variable d’objet de cet exemple ne contient donc pas l’instance d’objet. Au lieu de cela, il contient un pointeur (ou une référence) sur L'emplacement en mémoire où l'objet existe

var object = new Object();

si vous affectez une variable à une autre, chaque variable obtient une copie du pointeur et toutes deux référencent toujours le même objet dans memory.

var object1 = new Object();
var object2 = object1;

 Two variables pointing to one object

JavaScript est une langue garbage-collection, vous n’avez donc pas vraiment besoin de vous préoccuper des allocations de mémoire lorsque vous utilisez des types de référence. Toutefois, mieux vaut déréférencer les objets dont vous n’avez plus besoin pour que la corbeille collecteur peut libérer cette mémoire. La meilleure façon de faire est de régler le variable d'objet à null.

var object1 = new Object();
// do something
object1 = null; // dereference

Dereferencing objects est particulièrement important dans les très grandes applications utilisant des millions d'objets.

des principes de JavaScript orienté objet - NICHOLAS C. ZAKAS

0
Ani Naslyan