Dowiedz się, jak mierzyć wykorzystanie pamięci przez stronę internetową w wersji produkcyjnej w celu wykrywania regresji.
Przeglądarki automatycznie zarządzają pamięcią stron internetowych. Za każdym razem, gdy strona internetowa tworzy obiekt, przeglądarka przydzieli mu fragment pamięci „niestandardowo” do i przechowywać obiekt. Pamięć jest skończonym zasobem, więc przeglądarka czyszczenia pamięci, aby wykryć, kiedy obiekt nie jest już potrzebny, i zwolnić go bazowego fragmentu pamięci.
Wykrywanie nie jest jednak idealne, została udowodniona, że idealne wykrywanie jest zadaniem niemożliwym. Dlatego przeglądarki traktują w przybliżeniu pojęcie „obiektu jest potrzebna” gdzie obiekt jest osiągalny. Jeśli strona internetowa nie może i docierać do obiektu za pomocą jego zmiennych i pól innych osiągalnych obiektów, przeglądarka może bezpiecznie odzyskać obiekt. Różnica między tymi prowadzi do wycieków pamięci, co ilustruje następujący przykład.
const object = {a: new Array(1000), b: new Array(2000)};
setInterval(() => console.log(object.a), 1000);
W tym przypadku większa tablica b
nie jest już potrzebna, ale przeglądarka nie
Odzyska go, ponieważ jest nadal dostępny przez object.b
w wywołaniu zwrotnym. Zatem
spowoduje wyciek pamięci większej tablicy.
Wycieki pamięci są powszechne w internecie. Wprowadzenie tej funkcji jest proste – zapominasz wyrejestrować detektor zdarzeń, przez przypadek przechwytywanie obiektów z elementu iframe przez niezamykanie instancji roboczej przez kumulowanie obiektów w tablicach itd. Jeśli strona internetowa ma wyciek pamięci, wykorzystanie pamięci rośnie z czasem, a strona działa wolno na większą skalę.
Pierwszym krokiem do rozwiązania tego problemu jest jego pomiar. Nowy
performance.measureUserAgentSpecificMemory()
API umożliwia programistom:
mierzyć wykorzystanie pamięci przez strony internetowe w środowisku produkcyjnym i w ten sposób wykrywać pamięć.
wycieku, które przechodzą lokalne testy.
Czym performance.measureUserAgentSpecificMemory()
różni się od starszej wersji interfejsu API performance.memory
?
Jeśli znasz już niestandardowy interfejs API performance.memory
,
możesz zastanawiać się, czym różni się od niego nowy interfejs API. Główna różnica polega na tym,
że stary interfejs API zwraca rozmiar stosu JavaScript, a nowy
szacuje ilość pamięci wykorzystywanej przez stronę internetową. Ta różnica zmienia się
ważne, gdy Chrome współdziele tę samą stertę z wieloma stronami internetowymi (lub
wiele wystąpień tej samej strony internetowej). W takich przypadkach wynikiem starego argumentu
Interfejs API może być dowolnie wyłączony. Stary interfejs API został zdefiniowany w
pojęć związanych z implementacją, takich jak „sterta”, ustandaryzowanie tych rozwiązań jest beznadziejne.
Kolejna różnica polega na tym, że nowy interfejs API dokonuje pomiaru pamięci podczas czyszczenia pamięci. Pozwala to zmniejszyć szum w wynikach, ale może to zająć do czasu uzyskania wyników. Pamiętaj, że inne przeglądarki mogą zdecydować się wdrożyć nowy interfejs API bez konieczności czyszczenia pamięci.
Sugerowane zastosowania
Wykorzystanie pamięci przez stronę internetową zależy od czasu wystąpienia zdarzeń, działań użytkownika do czyszczenia pamięci. Dlatego interfejs API do pomiaru pamięci jest przeznaczony agregacji danych o wykorzystaniu pamięci z środowiska produkcyjnego. wyniki poszczególnych rozmów. są mniej przydatne. Przykładowe przypadki użycia:
- wykrywanie regresji podczas wdrażania nowej wersji strony internetowej w celu wychwytywania nowych wycieków pamięci;
- Testy A/B nowej funkcji pozwalające ocenić jej wpływ na pamięć i wykryć jej wycieki.
- Korelowanie wykorzystania pamięci z czasem trwania sesji w celu sprawdzenia obecności lub braku wycieków pamięci.
- Powiązanie wykorzystania pamięci ze wskaźnikami o użytkownikach w celu poznania ogólnego wpływu wykorzystania pamięci.
Zgodność z przeglądarką
Obecnie ten interfejs API jest obsługiwany tylko w przeglądarkach opartych na Chromium (od Chrome 89). wynik działania interfejsu API jest w dużym stopniu zależny od wdrożenia, ponieważ przeglądarki na różne sposoby przedstawiania obiektów w pamięci szacuję wykorzystanie pamięci. Przeglądarki mogą wykluczyć niektóre regiony pamięci z czy odpowiednie rozliczanie jest zbyt kosztowne lub niewykonalne. Wyniki nie można porównywać w różnych przeglądarkach. Istotne jest wyłącznie porównanie wyników dla tej samej przeglądarki.
Jak korzystać z aplikacji performance.measureUserAgentSpecificMemory()
Wykrywanie cech
Funkcja performance.measureUserAgentSpecificMemory
będzie niedostępna lub może
wystąpi błąd SecurityError, jeśli środowisko wykonawcze nie zostanie wypełnione.
wymagania dotyczące bezpieczeństwa związane z zapobieganiem wyciekom informacji z innych domen.
Opiera się na izolacji zasobów z innych domen, co strona internetowa może aktywować.
przez ustawienie nagłówków COOP+COEP.
Wsparcie można wykryć w czasie działania:
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);
}
Testy lokalne
Chrome mierzy pamięć podczas czyszczenia pamięci, co oznacza, że że interfejs API nie realizuje od razu obietnicy wyników i czeka na potrzeby kolejnego czyszczenia pamięci.
Wywołanie interfejsu API wymusza odśmiecanie pamięci po upływie czasu oczekiwania, który jest
jest ustawiony na 20 sekund, ale może nastąpić wcześniej. Uruchamianie Chrome na
Flaga wiersza poleceń --enable-blink-features='ForceEagerMeasureMemory'
ogranicza
limit czasu wynosi zero i jest przydatny przy lokalnym debugowaniu i testowaniu.
Przykład
Zalecanym zastosowaniem interfejsu API jest zdefiniowanie globalnego monitora pamięci, który
próbkuje wykorzystanie pamięci dla całej strony internetowej i wysyła wyniki na serwer
do agregacji i analizy. Najprostszym sposobem jest próbkowanie okresowo, przez
przykładowy tekst co M
min. Powoduje to jednak uprzedzenia danych, ponieważ
między próbkami mogą wystąpić szczyty pamięci.
Ten przykład pokazuje, jak obiektywnych pomiarów pamięci przy użyciu procesu Poissona, który gwarantuje, że prawdopodobieństwo pojawienia się próbek w dowolnym momencie jest jednakowe (demonstracja, źródło).
Najpierw zdefiniuj funkcję, która planuje następny pomiar pamięci za pomocą funkcji
setTimeout()
z interwałem losowym.
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);
}
Funkcja measurementInterval()
oblicza losowy interwał w milisekundach
dzięki czemu średnio co 5 minut jest wykonywany 1 pomiar. Zobacz Wykładnicze
rozkładu, jeśli interesuje Cię funkcja matematyczna.
function measurementInterval() {
const MEAN_INTERVAL_IN_MS = 5 * 60 * 1000;
return -Math.log(Math.random()) * MEAN_INTERVAL_IN_MS;
}
Na koniec asynchroniczna funkcja performMeasurement()
wywołuje interfejs API, rekordy
i zaplanuje następny pomiar.
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();
}
Na koniec rozpocznij pomiary.
// Start measurements.
scheduleMeasurement();
Wynik może wyglądać tak:
// 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']
},
],
}
Szacowane całkowite wykorzystanie pamięci jest zwracane w polu bytes
. Ta wartość to
zależą od implementacji i nie można ich porównywać w różnych przeglądarkach. Może
nawet zmieniać wersję tej samej przeglądarki. Wartość obejmuje
Pamięć JavaScript i DOM wszystkich elementów iframe, powiązanych okien i instancji roboczych w
w bieżącym procesie.
Lista breakdown
zawiera dodatkowe informacje o używanej pamięci. Każdy
wpis opisuje część pamięci i przypisuje ją do zbioru
okien, elementów iframe i instancji roboczych identyfikowanych przez adres URL. Pole types
zawiera listę
typy pamięci w danej implementacji powiązane z pamięcią.
Ważne jest, aby wszystkie listy traktować jako ogólne i nie kodować na stałe
dla konkretnej przeglądarki. Na przykład niektóre przeglądarki mogą
zwraca pusty atrybut breakdown
lub attribution
. Inne przeglądarki mogą
zwracają w funkcji attribution
wiele wpisów wskazujących, że nie mogą ich rozróżnić
który z tych wpisów jest właścicielem pamięci.
Prześlij opinię
Zespół Web Performance Community Group i zespół Chrome chętnie
aby poznać Twoją opinię i doświadczenia
performance.measureUserAgentSpecificMemory()
Opowiedz nam o konstrukcji interfejsu API
Czy jest coś, co w interfejsie API nie działa zgodnie z oczekiwaniami? Czy są brakuje właściwości, które są niezbędne do realizacji pomysłu? Zgłoś problem ze specyfikacją dotyczącą performance.measureUserAgentSpecificMemory() na GitHubie lub dodać do swoje przemyślenia na temat istniejącego problemu.
Zgłoś problem z implementacją
Czy wystąpił błąd z implementacją Chrome? Czy wdrożenie
różni się od specyfikacji? Zgłoś błąd na new.crbug.com. Koniecznie
Podaj jak najwięcej szczegółów, podaj proste instrukcje odtwarzania filmu,
błąd i ustaw opcję Komponenty na Blink>PerformanceAPIs
.
Usługa Glitch świetnie nadaje się do szybkiego i łatwego udostępniania poprawek.
Pokaż wsparcie
Czy zamierzasz korzystać z usługi performance.measureUserAgentSpecificMemory()
? Twoje poparcie publiczne
pomaga zespołowi Chrome ustalać priorytety funkcji i pokazuje innym dostawcom przeglądarek,
jest ich wsparcie. Wyślij tweeta na adres @ChromiumDev
i daj nam znać, gdzie i jak go używasz.
Przydatne linki
- Wyjaśnienie
- Prezentacja | Źródło wersji demonstracyjnej
- Śledzenie błędu
- Wpis na temat ChromeStatus.com
- Zmiany od wersji Origin próbny API
- Zakończona wersja próbna origin
Podziękowania
Dziękujemy Domenic Denicola, Yoav Weissowi i Mathiasowi Bynensowi za recenzje projektów API. oraz Dominik Inführ, Hannes Payer, Kentaro Hara, Michael Lippautz w celu weryfikacji kodu. w Chrome. Dziękuję również Per Parker, Philipp Weis, Olga Belomestnykh, Matthew Bolohan i Neil Mckay za przekazanie cennych opinii użytkowników, i usprawniliśmy interfejs API.
Baner powitalny, autor: Harrison Broadbent, Unsplash