Gesamtspeichernutzung Ihrer Webseite mit measureUserAgentSpecificMemory() überwachen

Hier erfahren Sie, wie Sie die Arbeitsspeichernutzung Ihrer Webseite in der Produktion messen, um Regressionen zu erkennen.

Brendan Kenny
Brendan Kenny
Ulan Degenbaev
Ulan Degenbaev

Browser verwalten den Arbeitsspeicher von Webseiten automatisch. Wenn eine Webseite ein Objekt erstellt, weist der Browser „im Hintergrund“ einen Teil des Arbeitsspeichers zu bis das Objekt speichern. Da der Arbeitsspeicher eine endliche Ressource ist, führt der Browser automatische Speicherbereinigung, um zu erkennen, wann ein Objekt nicht mehr benötigt wird, und den zugrunde liegenden Speicherblock.

Die Erkennung ist jedoch nicht perfekt, erwiesen sich als perfekte Erkennungsmechanismen. ist eine unmögliche Aufgabe. Daher verwenden Browser dem Konzept eines "Objekts erforderlich“ mit dem Konzept „ein Objekt ist erreichbar“. Wenn die Webseite um ein Objekt über seine Variablen und die Felder anderer erreichbarer Objekte zu erreichen, kann der Browser das Objekt sicher zurückfordern. Der Unterschied zwischen diesen zwei Faktoren zu Speicherlecks führen, wie im folgenden Beispiel dargestellt.

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

Hier wird das größere Array b nicht mehr benötigt, der Browser reaktiviere es, da es immer noch über object.b im Callback erreichbar ist. Das heißt: dass der Arbeitsspeicher des größeren Arrays durch Speicherlecks verursacht wird.

Im Web treten häufig Speicherlecks auf. Sie können einen Ereignis-Listener hinzufügen, indem Sie vergessen, die Registrierung eines Event-Listeners aufzuheben, versehentlich Objekte aus einem iFrame erfassen, indem ein Worker nicht geschlossen wird, das Ansammeln von Objekten in Arrays usw. Wenn auf einer Webseite Speicherlecks auftreten, steigt mit der Zeit die Speichernutzung und die Webseite wirkt langsam und bei den Nutzenden aufgebläht.

Der erste Schritt zur Lösung dieses Problems besteht darin, es zu messen. Das neue Mit der performance.measureUserAgentSpecificMemory() API können Entwickler die Arbeitsspeichernutzung ihrer Webseiten in der Produktion messen und so Arbeitsspeicher die bei lokalen Tests durchfallen.

Wie unterscheidet sich performance.measureUserAgentSpecificMemory() von der alten performance.memory API?

Wenn Sie mit der vorhandenen nicht standardmäßigen performance.memory API vertraut sind, fragen Sie sich vielleicht, inwiefern sich die neue API von ihr unterscheidet. Der Hauptunterschied ist dass die alte API die Größe des JavaScript-Heaps zurückgibt, während die neue API schätzt den von der Webseite genutzten Arbeitsspeicher. Diese Differenz ergibt sich dann wichtig, wenn Chrome denselben Heap mit mehreren Webseiten teilt (oder mehrere Instanzen derselben Webseite). In solchen Fällen wird das Ergebnis der alten API kann beliebig deaktiviert sein. Da die alte API in Implementierungsspezifische Begriffe wie „Heap“ und eine Standardisierung sind hoffnungslos.

Ein weiterer Unterschied besteht darin, dass die neue API automatische Speicherbereinigung. Dadurch wird das Rauschen in den Ergebnissen reduziert, es kann jedoch bis die Ergebnisse vorliegen. Andere Browser entscheiden möglicherweise, implementieren Sie die neue API, ohne die automatische Speicherbereinigung zu verwenden.

Empfohlene Anwendungsfälle

Die Arbeitsspeichernutzung einer Webseite hängt vom Timing von Ereignissen, automatische Speicherbereinigungen. Deshalb ist die Memory Measurement API für Daten zur Speichernutzung aus der Produktion werden zusammengefasst. Ergebnisse einzelner Anrufe weniger nützlich sind. Beispiele für Anwendungsfälle:

  • Regressionserkennung während des Roll-outs einer neuen Version der Webseite, um neue Speicherlecks zu erkennen.
  • A/B-Tests einer neuen Funktion, um die Auswirkungen auf den Arbeitsspeicher zu bewerten und Speicherlecks zu erkennen.
  • Korrelieren der Arbeitsspeichernutzung und der Sitzungsdauer, um das Vorhandensein oder Fehlen von Speicherlecks zu prüfen.
  • Arbeitsspeichernutzung mit Nutzermesswerten korrelieren, um die Gesamtauswirkungen der Arbeitsspeichernutzung zu verstehen.

Browserkompatibilität

Unterstützte Browser

  • Chrome: 89. <ph type="x-smartling-placeholder">
  • Edge: 89. <ph type="x-smartling-placeholder">
  • Firefox: nicht unterstützt <ph type="x-smartling-placeholder">
  • Safari: nicht unterstützt. <ph type="x-smartling-placeholder">

Quelle

Derzeit wird die API ab Chrome 89 nur in Chromium-basierten Browsern unterstützt. Die Das Ergebnis des APIs ist stark implementierungsabhängig, da Browser verschiedene Möglichkeiten, Objekte im Speicher darzustellen, die die Arbeitsspeichernutzung geschätzt wird. Browser schließen möglicherweise einige Speicherbereiche aus wenn eine ordnungsgemäße Buchhaltung zu teuer oder unmöglich ist. Dementsprechend werden die Ergebnisse können nicht browserübergreifend verglichen werden. Es ist nur sinnvoll, die Werte Ergebnisse für denselben Browser.

performance.measureUserAgentSpecificMemory() verwenden

Funktionserkennung

Die Funktion performance.measureUserAgentSpecificMemory ist nicht verfügbar oder kann schlägt mit einem SecurityError fehl, wenn die Ausführungsumgebung Sicherheitsanforderungen zur Vermeidung von ursprungsübergreifenden Informationslecks. Es basiert auf der ursprungsübergreifenden Isolierung, die von einer Webseite aktiviert werden kann. indem Sie COOP+COEP-Header festlegen.

Unterstützung während der Laufzeit wird erkannt:

if (!window.crossOriginIsolated) {
  console.log('performance.measureUserAgentSpecificMemory() is only available in cross-origin-isolated pages');
} else if (!performance.measureUserAgentSpecificMemory) {
  console.log('performance.measureUserAgentSpecificMemory() is not available in this browser');
} else {
  let result;
  try {
    result = await performance.measureUserAgentSpecificMemory();
  } catch (error) {
    if (error instanceof DOMException && error.name === 'SecurityError') {
      console.log('The context is not secure.');
    } else {
      throw error;
    }
  }
  console.log(result);
}

Lokales Testen

Chrome führt während der automatischen Speicherbereinigung dass die API das Ergebnisversprechen nicht sofort auflöst, sondern stattdessen wartet für die nächste automatische automatische Speicherbereinigung.

Der Aufruf der API erzwingt nach einer Zeitüberschreitung eine automatische Speicherbereinigung, die derzeit auf 20 Sekunden festgelegt. Starten von Chrome mit dem Befehlszeilen-Flag --enable-blink-features='ForceEagerMeasureMemory' reduziert auf null setzen. Dies ist nützlich für das lokale Debugging und Testen.

Beispiel

Es empfiehlt sich, für die API einen globalen Speichermonitor zu definieren, prüft die Arbeitsspeichernutzung der gesamten Webseite und sendet die Ergebnisse an einen Server für Aggregation und Analyse. Die einfachste Methode besteht darin, Beispiel alle M Minuten. Dies führt jedoch zu Verzerrungen der Daten, zwischen den Stichproben zu Speicherspitzen führen.

Das folgende Beispiel zeigt, wie Sie Arbeitsspeichermessungen mithilfe eines Poisson-Prozesses, garantiert, dass Stichproben mit gleicher Wahrscheinlichkeit zu jedem Zeitpunkt auftreten werden. (Demo, Quelle)

Definieren Sie zunächst eine Funktion, die die nächste Arbeitsspeichermessung mithilfe setTimeout() mit einem zufälligen Intervall.

function scheduleMeasurement() {
  // Check measurement API is available.
  if (!window.crossOriginIsolated) {
    console.log('performance.measureUserAgentSpecificMemory() is only available in cross-origin-isolated pages');
    console.log('See https://web.dev/coop-coep/ to learn more')
    return;
  }
  if (!performance.measureUserAgentSpecificMemory) {
    console.log('performance.measureUserAgentSpecificMemory() is not available in this browser');
    return;
  }
  const interval = measurementInterval();
  console.log(`Running next memory measurement in ${Math.round(interval / 1000)} seconds`);
  setTimeout(performMeasurement, interval);
}

Die Funktion measurementInterval() berechnet ein zufälliges Intervall in Millisekunden. sodass im Durchschnitt alle fünf Minuten eine Messung erfolgt. Siehe Exponentiell Verteilung, wenn Sie mehr über die mathematischen Funktionen der Funktion erfahren möchten.

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

Schließlich ruft die asynchrone performMeasurement()-Funktion die API auf. das Ergebnis und plant die nächste Messung.

async function performMeasurement() {
  // 1. Invoke performance.measureUserAgentSpecificMemory().
  let result;
  try {
    result = await performance.measureUserAgentSpecificMemory();
  } catch (error) {
    if (error instanceof DOMException && error.name === 'SecurityError') {
      console.log('The context is not secure.');
      return;
    }
    // Rethrow other errors.
    throw error;
  }
  // 2. Record the result.
  console.log('Memory usage:', result);
  // 3. Schedule the next measurement.
  scheduleMeasurement();
}

Beginnen Sie nun mit der Messung.

// Start measurements.
scheduleMeasurement();

Das Ergebnis könnte so aussehen:

// Console output:
{
  bytes: 60_100_000,
  breakdown: [
    {
      bytes: 40_000_000,
      attribution: [{
        url: 'https://example.com/',
        scope: 'Window',
      }],
      types: ['JavaScript']
    },

    {
      bytes: 20_000_000,
      attribution: [{
          url: 'https://example.com/iframe',
          container: {
            id: 'iframe-id-attribute',
            src: '/iframe',
          },
          scope: 'Window',
      }],
      types: ['JavaScript']
    },

    {
      bytes: 100_000,
      attribution: [],
      types: ['DOM']
    },
  ],
}

Die Schätzung der gesamten Arbeitsspeichernutzung wird im Feld bytes zurückgegeben. Dieser Wert ist sind sehr implementierungsabhängig und können nicht browserübergreifend verglichen werden. Möglicherweise und sogar zwischen verschiedenen Versionen desselben Browsers wechseln. Der Wert umfasst JavaScript- und DOM-Speicher aller iFrames, verwandten Fenster und Web Worker in des aktuellen Prozesses.

Die Liste breakdown enthält weitere Informationen zum verwendeten Arbeitsspeicher. Jedes einen Teil des Arbeitsspeichers beschreibt und einer Reihe von Fenster, iFrames und Worker, die durch eine URL identifiziert werden. Im Feld types werden die implementierungsspezifischen Speichertypen, die dem Arbeitsspeicher zugeordnet sind.

Es ist wichtig, alle Listen generisch zu behandeln und nicht hart zu codieren. für einen bestimmten Browser. Einige Browser können zum Beispiel ein leeres breakdown oder ein leeres attribution zurückgeben. Andere Browser Mehrere Einträge in attribution zurückgeben, die angeben, dass sie nicht unterscheiden konnten welcher dieser Einträge der Speicher gehört.

Feedback

Die Web Performance Community Group und das Chrome-Team um mehr über Ihre Gedanken und Erfahrungen mit performance.measureUserAgentSpecificMemory()

Informationen zum API-Design

Gibt es etwas an der API, das nicht wie erwartet funktioniert? Oder gibt es fehlende Eigenschaften, die Sie für die Umsetzung Ihrer Idee benötigen? Spezifikationsproblem melden unter performance.measureUserAgentSpecificMemory() GitHub-Repository oder fügen Sie zu einem bestehenden Problem äußern.

Problem mit der Implementierung melden

Haben Sie bei der Implementierung von Chrome einen Fehler gefunden? Oder ist die Implementierung von der Spezifikation abweichen? Melde einen Fehler unter new.crbug.com. Achten Sie darauf, so viele Details wie möglich aufführen, einfache Anweisungen zum Reproduzieren den Fehler beheben und Components auf Blink>PerformanceAPIs gesetzt haben. Glitch eignet sich hervorragend, um schnelle und einfache Reproduktionen zu teilen.

Support anzeigen

Möchtest du performance.measureUserAgentSpecificMemory() verwenden? Deine öffentliche Unterstützung unterstützt das Chrome-Team bei der Priorisierung von Funktionen und zeigt anderen Browseranbietern, ist es wichtig, sie zu unterstützen. Tweet an @ChromiumDev senden und teilen Sie uns mit, wo und wie Sie sie nutzen.

Nützliche Links

Danksagungen

Vielen Dank an Domenic Denicola, Yoav Weiss und Mathias Bynens für API-Design-Rezensionen. und Dominik Inführ, Hannes Payer, Kentaro Hara und Michael Lippautz für Code Reviews in Chrome. Ich danke auch Per Parker, Philipp Weis, Olga Belomestnykh, Matthew, Bolohan und Neil Mckay für ihr wertvolles Feedback von Nutzenden, die API verbessert.

Hero-Image von Harrison Broadbent auf Unsplash