L'auteur de l'article, dont nous publions la traduction aujourd'hui, explique comment surveiller la mémoire allouée aux pages Web. Une attention particuliÚre à la mémoire des pages travaillant en production permet de maintenir la productivité des projets Web à un niveau élevé.
Les navigateurs contrĂŽlent automatiquement la mĂ©moire allouĂ©e aux pages Web. Lorsqu'une page crĂ©e un objet, le navigateur, en utilisant ses mĂ©canismes internes, alloue de la mĂ©moire pour stocker cet objet. Ătant donnĂ© que la mĂ©moire n'est pas une ressource infinie, le navigateur effectue pĂ©riodiquement la collecte des ordures, au cours de laquelle les objets inutiles sont dĂ©tectĂ©s et la mĂ©moire qu'ils occupent est effacĂ©e. Le processus de dĂ©tection de tels objets n'est cependant pas idĂ©al. Il a Ă©tĂ© prouvĂ©que l'identification absolument exacte et complĂšte de ces objets est une tĂąche insoluble. En consĂ©quence, les navigateurs remplacent l'idĂ©e de trouver des «objets inutiles» par l'idĂ©e de trouver des «objets inaccessibles». Si une page Web ne peut pas accĂ©der Ă l'objet via ses variables et champs d'autres objets qui lui sont accessibles, cela signifie que le navigateur peut effacer en toute sĂ©curitĂ© la mĂ©moire occupĂ©e par un tel objet. La diffĂ©rence entre «inutile» et «inaccessible» entraĂźne des fuites de mĂ©moire, comme illustrĂ© dans l'exemple suivant:const object = { a: new Array(1000), b: new Array(2000) };
setInterval(() => console.log(object.a), 1000);
Il existe un grand tableau inutile ici b
, mais le navigateur ne libÚre pas la mémoire qu'il occupe en raison du fait qu'il est accessible via la propriété d'objet object.b
dans le rappel. Par conséquent, la mémoire occupée par ce tableau fuit.Les fuites de mémoire sont fréquentes dans le développement Web. Ils apparaissent trÚs facilement dans les programmes lorsque, par exemple, les développeurs oublient de se désinscrire de l'écouteur d'événements, lorsqu'ils capturent accidentellement des objets dans un élément iframe
, lorsqu'ils oublient de fermer le travailleur, lorsqu'ils collectent des objets dans des tableaux. Si une page Web présente des fuites de mémoire, cela conduit au fait qu'au fil du temps, la consommation de mémoire de la page augmente. Une telle page semble lente et lente pour les utilisateurs.La premiÚre étape pour résoudre ce problÚme consiste à prendre des mesures. La nouvelle API performance.measureMemory () permet aux développeurs de mesurer l'utilisation de la mémoire par les pages Web en production et, par conséquent, de détecter les fuites de mémoire qui glissent à travers les tests locaux.En quoi la nouvelle API performance.measureMemory () est-elle différente de l'ancienne performance.memory?
Si vous ĂȘtes familiarisĂ© avec l'API non standard existante performance.memory
, alors vous pourriez ĂȘtre intĂ©ressĂ© par la question de savoir comment la nouvelle API diffĂšre de l'ancienne. La principale diffĂ©rence est que l'ancienne API renvoie la taille du tas JavaScript et la nouvelle Ă©value l'utilisation de la mĂ©moire de la page Web entiĂšre. Cette distinction est importante lorsque Chrome organise le partage de segments de mĂ©moire entre plusieurs pages Web (ou plusieurs instances de la mĂȘme page). Dans de tels cas, les rĂ©sultats renvoyĂ©s par l'ancienne API peuvent ĂȘtre dĂ©formĂ©s. Ătant donnĂ© que l'ancienne API est dĂ©finie en termes spĂ©cifiques Ă l'implĂ©mentation, comme un tas, la normalisation est une entreprise dĂ©sespĂ©rĂ©e.Une autre diffĂ©rence est que dans Chrome, la nouvelle API prend des mesures de mĂ©moire lors de la collecte des ordures. Cela rĂ©duit le «bruit» dans les rĂ©sultats de mesure, mais peut prendre un certain temps pour obtenir les rĂ©sultats. Veuillez noter que les crĂ©ateurs d'autres navigateurs peuvent dĂ©cider d'implĂ©menter la nouvelle API sans se lier Ă la rĂ©cupĂ©ration de place.Façons recommandĂ©es d'utiliser la nouvelle API
L'utilisation de la mémoire par les pages Web dépend de l'occurrence d'événements, des actions de l'utilisateur, de la récupération de place. C'est pourquoi l'API est performance.measureMemory()
conçue pour Ă©tudier le niveau d'utilisation de la mĂ©moire en production. Les rĂ©sultats de l'appel de cette API dans un environnement de test sont moins utiles. Voici des exemples d'options pour l'utiliser:Actuellement, l'API en question n'est prise en charge que dans Chrome 83, selon le schĂ©ma Origin Trial. Les rĂ©sultats renvoyĂ©s par l'API dĂ©pendent fortement de l'implĂ©mentation, car diffĂ©rents navigateurs utilisent diffĂ©rentes maniĂšres de reprĂ©senter les objets en mĂ©moire et diffĂ©rentes façons d'Ă©valuer le niveau d'utilisation de la mĂ©moire. Les navigateurs peuvent exclure certaines zones de mĂ©moire de la comptabilitĂ© si la comptabilitĂ© complĂšte de toute la mĂ©moire utilisĂ©e est une tĂąche dĂ©raisonnablement difficile ou impossible. Par consĂ©quent, nous pouvons dire que les rĂ©sultats produits par cette API dans diffĂ©rents navigateurs ne sont pas comparables. Il est logique de comparer uniquement les rĂ©sultats obtenus dans le mĂȘme navigateur.Avancement des travaux en cours
Utilisation de performance.measureMemory ()
â Activer la prise en charge de l'essai d'origine
L'API performance.measureMemory()
est disponible dans Chrome 83 selon le schĂ©ma d'essai d'origine. Cette phase devrait se terminer avec la sortie de Chrome 84. L'essai d'origine permet aux dĂ©veloppeurs de profiter des nouvelles fonctionnalitĂ©s de Chrome et de partager leurs commentaires sur la commoditĂ©, la convivialitĂ© et l'efficacitĂ© de ces fonctionnalitĂ©s avec la communautĂ© Web. Des dĂ©tails sur ce programme peuvent ĂȘtre trouvĂ©s ici . Vous pouvez vous abonner au programme sur la page d' inscription.âInscription au programme Origin Trial
- Demandez un jeton pour l'opportunité qui vous intéresse.
- Ajoutez le jeton aux pages du projet pilote. Il y a 2 façons de procéder:
- Ajoutez une
<meta>
balise origin-trial
au titre de chaque page. Par exemple, il pourrait ressembler Ă ceci: <meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">
. - Si vous avez accĂšs aux paramĂštres du serveur, il peut ajouter un jeton Ă l'aide d'un en-tĂȘte HTTP
Origin-Trial
. En consĂ©quence, l' en- tĂȘte de rĂ©ponse devrait apparaĂźtre quelque chose comme ce qui suit: Origin-Trial: TOKEN_GOES_HERE
.
âActiver une nouvelle fonctionnalitĂ© via les drapeaux Chrome
Afin d'expérimenter performance.measureMemory()
, pendant la distribution avec le jeton Origin Trial, vous devez activer le drapeau #experimental-web-platform-features
dans chrome://flags
.âVĂ©rification de l'utilisation de l'API
Un appel de fonction performance.measureMemory()
peut Ă©chouer, avec une SecurityError levĂ©e . Cela peut se produire si l'environnement ne rĂ©pond pas aux exigences de sĂ©curitĂ© pour les fuites d'informations. Lors du test Origin Trial dans Chrome, cette API nĂ©cessite l'inclusion de l' isolement du site . Lorsque l'API est prĂȘte pour une utilisation normale, elle s'appuiera sur la propriĂ©tĂ© crossOriginIsolated . Une page Web peut fonctionner dans ce mode en dĂ©finissant les en-tĂȘtes COOP et COEP .Voici un exemple de code:if (performance.measureMemory) {
let result;
try {
result = await performance.measureMemory();
} catch (error) {
if (error instanceof DOMException &&
error.name === "SecurityError") {
console.log("The context is not secure.");
} else {
throw error;
}
}
console.log(result);
}
âTest local
Chrome prend une mesure de mémoire lors de la collecte des ordures. Cela signifie que l'accÚs à l'API ne résout pas instantanément la promesse. Pour obtenir le résultat, vous devez attendre la prochaine session de récupération de place. L'API démarre de force la récupération de place aprÚs un certain délai, qui est actuellement défini sur 20 secondes. Si vous exécutez Chrome avec un indicateur de ligne de commande --enable-blink-features='ForceEagerMeasureMemory'
, le délai sera réduit à zéro, ce qui est utile pour le débogage local et les tests locaux.Exemple
Il est recommandĂ© d'utiliser la nouvelle API en dĂ©finissant un moniteur de mĂ©moire global qui mesure le niveau d'utilisation de la mĂ©moire de la page entiĂšre et envoie les rĂ©sultats au serveur, oĂč ils peuvent ĂȘtre agrĂ©gĂ©s et analysĂ©s. La façon la plus simple de travailler avec cette API est de prendre des mesures pĂ©riodiques. Par exemple, ils peuvent s'exĂ©cuter toutes les M
minutes. Cependant, cela introduit des distorsions dans les données, car des pics d'utilisation de la mémoire peuvent survenir entre les mesures. L'exemple suivant montre comment, à l' aide du processus de Poisson , effectuer des mesures sans erreurs systématiques. Cette approche garantit que les sessions de mesure peuvent, avec une probabilité égale, avoir lieu à tout moment ( voici une démonstration de cette approche,voici le code source).Tout d'abord, déclarez une fonction qui planifie le prochain démarrage d'une session pour mesurer la quantité de mémoire consommée à l'aide d'une fonction setTimeout()
avec un intervalle dĂ©fini de maniĂšre alĂ©atoire. Cette fonction doit ĂȘtre appelĂ©e aprĂšs le chargement de la page dans la fenĂȘtre du navigateur.function scheduleMeasurement() {
if (!performance.measureMemory) {
console.log("performance.measureMemory() is not available.");
return;
}
const interval = measurementInterval();
console.log("Scheduling memory measurement in " +
Math.round(interval / 1000) + " seconds.");
setTimeout(performMeasurement, interval);
}
window.onload = function () {
scheduleMeasurement();
}
La fonction measurementInterval()
trouve un intervalle alĂ©atoire, exprimĂ© en millisecondes, dĂ©fini de telle sorte qu'une mesure soit effectuĂ©e environ toutes les cinq minutes. Si vous ĂȘtes intĂ©ressĂ© par les concepts mathĂ©matiques sur lesquels cette fonction est basĂ©e, lisez la distribution exponentielle .function measurementInterval() {
const MEAN_INTERVAL_IN_MS = 5 * 60 * 1000;
return -Math.log(Math.random()) * MEAN_INTERVAL_IN_MS;
}
Par conséquent, la fonction asynchrone performMeasurement()
appelle notre API, enregistre le résultat et planifie la prochaine mesure.async function performMeasurement() {
let result;
try {
result = await performance.measureMemory();
} catch (error) {
if (error instanceof DOMException &&
error.name === "SecurityError") {
console.log("The context is not secure.");
return;
}
throw error;
}
console.log("Memory usage:", result);
scheduleMeasurement();
}
Les résultats des mesures peuvent ressembler à ceci:
{
bytes: 60_000_000,
breakdown: [
{
bytes: 40_000_000,
attribution: ["https://foo.com"],
userAgentSpecificTypes: ["Window", "JS"]
},
{
bytes: 20_000_000,
attribution: ["https://foo.com/iframe"],
userAgentSpecificTypes: ["Window", "JS"]
}
]
}
Une estimation du niveau global d'utilisation de la mémoire s'affiche dans le champ bytes
. Pour dĂ©river cette estimation, les sĂ©parateurs des chiffres sont utilisĂ©s. Ces valeurs dĂ©pendent fortement de l'implĂ©mentation. S'ils sont reçus pour diffĂ©rents navigateurs, vous ne pouvez pas les comparer. La façon dont ils sont obtenus peut varier mĂȘme dans diffĂ©rentes versions du mĂȘme navigateur. Pendant la durĂ©e du programme Origin Trial, les valeurs de retour incluent des indicateurs d'utilisation de la mĂ©moire JavaScript par la fenĂȘtre principale, des indicateurs d'utilisation de la mĂ©moire des Ă©lĂ©ments iframe
du mĂȘme site et des indicateurs de fenĂȘtres associĂ©es. Lorsque l'API est prĂȘte, cette valeur reprĂ©sentera des informations sur la mĂ©moire consommĂ©e par JavaScript, le DOM, tous les Ă©lĂ©ments iframe
associĂ©s aux fenĂȘtres et aux travailleurs Web.listebreakdown
donne des informations plus dĂ©taillĂ©es sur la mĂ©moire utilisĂ©e. Chaque entrĂ©e dĂ©crit un morceau de mĂ©moire et associe ce fragment Ă un ensemble de fenĂȘtres, d'Ă©lĂ©ments iframe
ou de travailleurs identifiés par une URL. Le champ userAgentSpecificTypes
répertorie les types de mémoire déterminés par les fonctionnalités d'implémentation.Il est important de considérer ces listes de maniÚre générale et de ne pas essayer, en s'appuyant sur les fonctionnalités d'un certain navigateur, d'analyser tout en fonction de celles-ci. Par exemple, certains navigateurs peuvent renvoyer une liste breakdown
vide ou des champs vides attribution
. D'autres navigateurs peuvent renvoyer attribution
plusieurs URL dans un élément , indiquant qu'ils ne peuvent pas identifier à laquelle de ces URL appartient la mémoire.Retour d'information
Le groupe de la communauté des performances Web et l'équipe de développement Chrome seront ravis de savoir ce que vous en pensez performance.measureMemory()
et d'en savoir plus sur votre expérience d'utilisation de cette API.Partagez vos idées sur le périphérique API avec nous
Y a-t-il quelque chose dans cette API qui ne fonctionne pas comme prĂ©vu? Peut-ĂȘtre qu'il manque quelque chose dont vous avez besoin pour mettre en Ćuvre votre idĂ©e? Ouvrez une nouvelle tĂąche dans le suivi de projet ou commentez une tĂąche existante.Signaler un problĂšme de mise en Ćuvre
Vous avez trouvĂ© un bug dans votre implĂ©mentation Chrome? Ou peut-ĂȘtre que la mise en Ćuvre est diffĂ©rente de la spĂ©cification? Enregistrez l'erreur ici: new.crbug.com . Essayez d'inclure autant de dĂ©tails que possible dans votre message, incluez des instructions simples sur la façon de reproduire l'erreur et indiquez que le problĂšme est liĂ© Ă Blink>PerformanceAPIs
. Glitch est un trÚs bon moyen de démontrer les erreurs .Soutenez-nous
performance.measureMemory()
Envisagez-vous d'utiliser ? Si c'est comme ça, dis nous en plus Ă propos. Ces histoires aident l'Ă©quipe de dĂ©veloppement Chrome Ă Ă©tablir des prioritĂ©s. Ces histoires montrent aux crĂ©ateurs d'autres navigateurs l'importance de prendre en charge de nouvelles fonctionnalitĂ©s. Si vous le souhaitez, envoyez un tweet Ă @ChromiumDev et dites-nous oĂč et comment vous utilisez la nouvelle API.Chers lecteurs! As-tu essayĂ© performance.measureMemory()
?