Überwachen des gesamten von einer Webseite verwendeten Speichers: performance.measureMemory ()

Der Autor des Artikels, dessen Übersetzung wir heute veröffentlichen, spricht darüber, wie der den Webseiten zugewiesene Speicher überwacht werden kann. Die sorgfältige Berücksichtigung des Gedächtnisses von Seiten, die in der Produktion arbeiten, trägt dazu bei, die Produktivität von Webprojekten auf einem hohen Niveau zu halten.



Browser steuern automatisch den Speicher, der Webseiten zugewiesen ist. Wenn eine Seite ein Objekt erstellt, weist der Browser mithilfe seiner internen Mechanismen Speicher zum Speichern dieses Objekts zu. Da der Speicher keine unendliche Ressource ist, führt der Browser regelmäßig eine Speicherbereinigung durch, bei der unnötige Objekte erkannt und der von ihnen belegte Speicher gelöscht wird. Der Prozess der Erkennung solcher Objekte ist jedoch nicht ideal. Es wurde bewiesendass eine absolut genaue und vollständige Identifizierung solcher Objekte eine unlösbare Aufgabe ist. Infolgedessen ersetzen Browser die Idee, „unnötige Objekte“ zu finden, durch die Idee, „nicht erreichbare Objekte“ zu finden. Wenn eine Webseite nicht über ihre Variablen und Felder anderer Objekte, auf die sie zugreifen kann, auf das Objekt zugreifen kann, bedeutet dies, dass der Browser den von einem solchen Objekt belegten Speicher sicher löschen kann. Der Unterschied zwischen "unnötig" und "nicht erreichbar" führt zu Speicherverlusten, wie im folgenden Beispiel dargestellt:

const object = { a: new Array(1000), b: new Array(2000) };
setInterval(() => console.log(object.a), 1000);

Hier gibt es ein großes unnötiges Array b, aber der Browser gibt den von ihm belegten Speicher nicht frei, da er über die Objekteigenschaft object.bim Rückruf erreichbar ist. Infolgedessen ist der von diesem Array belegte Speicher undicht.

Speicherlecks treten häufig in der Webentwicklung auf. Sie werden sehr leicht in Programmen angezeigt, wenn Entwickler beispielsweise vergessen, sich vom Ereignis-Listener abzumelden, wenn sie versehentlich Objekte in einem Element erfassen iframe, wenn sie vergessen, den Worker zu schließen, wenn sie Objekte in Arrays sammeln. Wenn eine Webseite Speicherlecks aufweist, führt dies dazu, dass der Speicherverbrauch der Seite mit der Zeit zunimmt. Eine solche Seite scheint für Benutzer langsam und langsam zu sein.

Der erste Schritt zur Lösung dieses Problems besteht darin, Messungen durchzuführen. Mit der neuen API " performance.measureMemory ()" können Entwickler die Speichernutzung von Webseiten in der Produktion messen und als Ergebnis Speicherlecks erkennen, die durch lokale Tests verrutschen.

Wie unterscheidet sich die neue Performance.measureMemory () - API von der alten Performance.memory?


Wenn Sie mit der vorhandenen nicht standardmäßigen API vertraut sind performance.memory, könnte Sie die Frage interessieren, wie sich die neue API von der alten unterscheidet. Der Hauptunterschied besteht darin, dass die alte API die Größe des JavaScript-Heaps zurückgibt und die neue die Speichernutzung der gesamten Webseite bewertet. Diese Unterscheidung ist wichtig, wenn Chrome die Heap-Freigabe zwischen mehreren Webseiten (oder mehreren Instanzen derselben Seite) organisiert. In solchen Fällen können die von der alten API zurückgegebenen Ergebnisse verzerrt sein. Da die alte API in implementierungsspezifischen Begriffen wie einem Heap definiert ist, ist die Standardisierung ein hoffnungsloses Geschäft.

Ein weiterer Unterschied besteht darin, dass die neue API in Chrome Speichermessungen beim Sammeln von Müll durchführt. Dies reduziert das „Rauschen“ in den Messergebnissen, kann jedoch einige Zeit dauern, bis die Ergebnisse vorliegen. Bitte beachten Sie, dass Entwickler anderer Browser möglicherweise entscheiden, die neue API zu implementieren, ohne an die Garbage Collection gebunden zu sein.

Empfohlene Möglichkeiten zur Verwendung der neuen API


Die Verwendung des Speichers durch Webseiten hängt vom Auftreten von Ereignissen, von Benutzeraktionen und von der Speicherbereinigung ab. Aus diesem Grund wurde die API performance.measureMemory()entwickelt, um den Grad der Speichernutzung in der Produktion zu untersuchen. Die Ergebnisse des Aufrufs dieser API in einer Testumgebung sind weniger nützlich. Hier sind Beispiele für Optionen zur Verwendung:

  • - .
  • A/B- , .
  • .
  • , . .


Derzeit wird die betreffende API gemäß dem Origin-Testschema nur in Chrome 83 unterstützt. Die von der API zurückgegebenen Ergebnisse hängen stark von der Implementierung ab, da verschiedene Browser unterschiedliche Arten der Darstellung von Objekten im Speicher und unterschiedliche Methoden zur Bewertung des Speicherbedarfs verwenden. Browser können einige Speicherbereiche von der Abrechnung ausschließen, wenn die vollständige Abrechnung des gesamten verwendeten Speichers eine unangemessen schwierige oder unmögliche Aufgabe ist. Infolgedessen können wir sagen, dass die von dieser API in verschiedenen Browsern erzeugten Ergebnisse nicht vergleichbar sind. Es ist sinnvoll, nur die Ergebnisse zu vergleichen, die im selben Browser erzielt wurden.

Aktueller Arbeitsfortschritt


SchrittBedingung
1. API-Erklärungen erstellen
Abgeschlossen
2. Erstellen eines Spezifikationsentwurfs
Durchgeführt
3. Feedback einholen und das Projekt abschließen
Durchgeführt
4. Origin-Testversuche
Durchgeführt
5. Starten Sie
Nicht angefangen

Verwenden von performance.measureMemory ()


▍ Aktivieren Sie die Origin-Testunterstützung


Die API performance.measureMemory()ist in Chrome 83 gemäß dem Origin-Testschema verfügbar. Diese Phase wird voraussichtlich mit der Veröffentlichung von Chrome 84 enden. Mit

Origin Trial können Entwickler die neuen Funktionen von Chrome nutzen und der Web-Community Feedback zu Komfort, Benutzerfreundlichkeit und Effektivität dieser Funktionen geben. Details zu diesem Programm finden Sie hier . Sie können das Programm auf der Registrierungsseite abonnieren .

▍Registrierung im Origin-Testprogramm


  1. Fordern Sie einen Token für die Gelegenheit an, an der Sie interessiert sind.
  2. Fügen Sie das Token zu den Seiten des Pilotprojekts hinzu. Es gibt zwei Möglichkeiten, dies zu tun:

    • Fügen Sie dem Titel jeder Seite ein <meta>Tag hinzu origin-trial. Zum Beispiel könnte es so aussehen : <meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">.
    • Wenn Sie Zugriff auf die Servereinstellungen haben, kann ein Token mithilfe eines HTTP-Headers hinzugefügt werden Origin-Trial. Infolgedessen sollte der Antwortheader wie folgt aussehen : Origin-Trial: TOKEN_GOES_HERE.

▍Eine neue Funktion über Chrome-Flags aktivieren


Um performance.measureMemory()mit dem Origin Trial-Token zu experimentieren , müssen Sie das Flag #experimental-web-platform-featuresin aktivieren chrome://flags.

▍Überprüfen der API-Verwendung


Ein Funktionsaufruf performance.measureMemory()kann fehlschlagen, wenn ein SecurityError ausgelöst wird . Dies kann passieren, wenn die Umgebung die Sicherheitsanforderungen für Informationslecks nicht erfüllt. Während des Origin-Testversuchs in Chrome erfordert diese API die Einbeziehung der Site-Isolation . Wenn die API für den normalen Gebrauch bereit ist, stützt sie sich auf die Eigenschaft crossOriginIsolated . Eine Webseite kann in diesem Modus betrieben werden, indem die Header COOP und COEP gesetzt werden .

Hier ist ein Beispielcode:

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);
}

▍Lokale Tests


Chrome führt beim Sammeln von Müll eine Speichermessung durch. Dies bedeutet, dass der Zugriff auf die API das Versprechen nicht sofort auflöst. Um das Ergebnis zu erhalten, müssen Sie auf die nächste Speicherbereinigungssitzung warten. Die API startet die Speicherbereinigung zwangsweise nach einem bestimmten Zeitlimit, das derzeit auf 20 Sekunden festgelegt ist. Wenn Sie Chrome mit einem Befehlszeilenflag ausführen --enable-blink-features='ForceEagerMeasureMemory', wird das Zeitlimit auf Null reduziert. Dies ist nützlich für lokales Debugging und lokale Tests.

Beispiel


Es wird empfohlen, die neue API zu verwenden, indem Sie einen globalen Speichermonitor definieren, der den Speicherbedarf der gesamten Seite misst und die Ergebnisse an den Server sendet, wo sie aggregiert und analysiert werden können. Der einfachste Weg, mit dieser API zu arbeiten, besteht darin, regelmäßige Messungen durchzuführen. Zum Beispiel können sie jede MMinute laufen . Dies führt jedoch zu Verzerrungen in den Daten, da zwischen den Messungen Spitzen in der Speichernutzung auftreten können. Das folgende Beispiel zeigt, wie mit dem Poisson-Verfahren Messungen frei von systematischen Fehlern durchgeführt werden können. Dieser Ansatz stellt sicher, dass Messsitzungen mit gleicher Wahrscheinlichkeit zu jedem Zeitpunkt stattfinden können ( hier ist eine Demonstration dieses Ansatzes,hier ist der Quellcode).

Deklarieren Sie zunächst eine Funktion, die den nächsten Start einer Sitzung plant, um die Menge des verbrauchten Speichers mithilfe einer Funktion setTimeout()mit einem zufällig festgelegten Intervall zu messen . Diese Funktion sollte nach dem Laden der Seite im Browserfenster aufgerufen werden.

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();
}

Die Funktion measurementInterval()findet ein zufälliges Intervall, ausgedrückt in Millisekunden, das so eingestellt ist, dass ungefähr alle fünf Minuten eine Messung durchgeführt wird. Wenn Sie an den mathematischen Konzepten interessiert sind, auf denen diese Funktion basiert, lesen Sie die Exponentialverteilung .

function measurementInterval() {
  const MEAN_INTERVAL_IN_MS = 5 * 60 * 1000;
  return -Math.log(Math.random()) * MEAN_INTERVAL_IN_MS;
}

Infolgedessen performMeasurement()ruft die asynchrone Funktion unsere API auf, zeichnet das Ergebnis auf und plant die nächste Messung.

async function performMeasurement() {
  // 1.  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.");
      return;
    }
    //    .
    throw error;
  }
  // 2.  .
  console.log("Memory usage:", result);
  // 3.   .
  scheduleMeasurement();
}

Die Messergebnisse können folgendermaßen aussehen:

// ,    :
{
  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"]
    }
  ]
}

Eine Schätzung der Gesamtspeicherauslastung wird im Feld angezeigt bytes. Bei der Ableitung dieser Schätzung werden die Trennzeichen der Ziffern von Zahlen verwendet. Diese Werte sind stark implementierungsabhängig. Wenn sie für verschiedene Browser empfangen werden, können Sie sie nicht vergleichen. Die Art und Weise, wie sie erhalten werden, kann auch in verschiedenen Versionen desselben Browsers variieren. Während das Origin-Testprogramm gültig ist, enthalten die Rückgabewerte Indikatoren für die Speichernutzung von JavaScript im Hauptfenster, Indikatoren für die Speichernutzung von Elementen iframederselben Site und Indikatoren für verwandte Fenster. Wenn die API bereit ist, repräsentiert dieser Wert Informationen über den von JavaScript, dem DOM, allen iframemit Windows und Web Workern verknüpften Speicher belegten Speicher .

Listebreakdowngibt detailliertere Informationen über den verwendeten Speicher. Jeder Eintrag beschreibt ein Stück Speicher und ordnet dieses Fragment einer Reihe von Fenstern, Elementen iframeoder Arbeitern zu, die durch eine URL identifiziert werden. Das Feld userAgentSpecificTypeslistet die Speichertypen auf, die durch die Implementierungsfunktionen bestimmt werden.

Es ist wichtig, diese Listen allgemein zu betrachten und nicht unter Verwendung der Funktionen eines bestimmten Browsers zu versuchen, alles zu analysieren, was auf ihnen basiert. Beispielsweise geben einige Browser möglicherweise leere Listen breakdownoder leere Felder zurück attribution. Andere Browser geben möglicherweise attributionmehrere URLs in einem Element zurück , was darauf hinweist, dass sie nicht genau bestimmen können, zu welcher dieser URLs der Speicher gehört.

Rückkopplung


Die Web Performance Community Group und das Chrome-Entwicklungsteam performance.measureMemory()erfahren gerne, woran Sie denken, und erfahren mehr über Ihre Erfahrungen mit dieser API.

Teilen Sie uns Ihre Ideen zum API-Gerät mit


Gibt es etwas in dieser API, das nicht wie erwartet funktioniert? Vielleicht fehlt etwas, das Sie brauchen, um Ihre Idee umzusetzen? Öffnen Sie eine neue Aufgabe im Projekt- Tracker oder kommentieren Sie eine vorhandene Aufgabe.

Ein Implementierungsproblem melden


Haben Sie einen Fehler in Ihrer Chrome-Implementierung gefunden? Oder hat sich herausgestellt, dass sich die Implementierung von der Spezifikation unterscheidet? Notieren Sie den Fehler hier: new.crbug.com . Versuchen Sie, so viele Details wie möglich in Ihre Nachricht aufzunehmen, geben Sie einfache Anweisungen zum Reproduzieren des Fehlers und geben Sie an, dass das Problem damit zusammenhängt Blink>PerformanceAPIs. Glitch ist ein sehr guter Weg, um Fehler zu demonstrieren .

Unterstütze uns


Planen performance.measureMemory()Sie zu verwenden ? Wenn ja, erzählen Sie uns davon. Diese Geschichten helfen dem Chrome-Entwicklungsteam, Prioritäten zu setzen. Diese Geschichten zeigen den Entwicklern anderer Browser, wie wichtig es ist, neue Funktionen zu unterstützen. Wenn Sie möchten, senden Sie einen Tweet an @ChromiumDev und teilen Sie uns mit, wo und wie Sie die neue API verwenden.

Liebe Leser! Hast du es versucht performance.measureMemory()?


All Articles