Работа мечты в один клик 💼

💭Мечтаешь работать в Сбере, но не хочешь проходить десять кругов HR-собеседований? Теперь это проще, чем когда-либо!
💡AI-интервью за 15 минут – и ты уже на шаг ближе к своей новой работе.
Как получить оффер? 📌 Зарегистрируйся 📌 Пройди AI-интервью 📌 Получи обратную связь сразу же!
HR больше не тянут время – рекрутеры свяжутся с тобой в течение двух дней! 🚀
Реклама. ПАО СБЕРБАНК, ИНН 7707083893. Erid 2VtzquscAwp
Когда веб-страница создаёт объект, браузер выделяет память для его хранения. Но объем памяти ограничен, и время от времени браузер выполняет сборку мусора. Однако если веб-страница не может достичь объекта через переменные и поля других доступных объектов, она может попытаться восстановить объект. Эти манипуляции приводят к утечкам памяти:
const object = { a: new Array(1000), b: new Array(2000) };
setInterval(() => console.log(object.a), 1000);
Массив b
больше
не нужен, но браузер его не восстанавливает, так как массив всё ещё доступен через
object.b
в коллбэке. То есть в большем массиве и происходит утечка
памяти.
К сожалению, утечки памяти широко
распространены в веб-разработке: здесь забыли отменить регистрацию event
listener
, там случайно начали использовать объекты из iframe
, а тут накапливаем объекты в
массивах... Утечки приводят к тому, что использование памяти страницей растёт, и она работает медленно.
Первый шаг в решении проблемы – её измерение. Новый API
performance.measureMemory()
позволяет разработчикам измерять использование
памяти страницей в процессе её работы и обнаружить утечки, которые могли проскользнуть во время тестирования.
Чем performance.measureMemory() отличается от performance.memory()?

Основное отличие старого и нового API заключается в том, что старый API возвращает размер кучи JavaScript, в то время как новый оценивает использование памяти веб-страницей целиком. Это различие становится особенно важным, когда в браузере одну и ту же кучу используют несколько веб-страниц или несколько экземпляров одной и той же страницы.
Еще одно отличие заключается в том, что новый API выполняет измерение памяти во время сборки мусора. Это уменьшает погрешность в результатах, но измерение может быть более продолжительным. Обратите внимание, что другие браузеры могут решить реализовать новый API, не учитывая сборку мусора.
Предлагаемые варианты использования
Использование памяти
зависит от времени событий, действий пользователя и сборок мусора. Поэтому API measureMemory()
предназначен для агрегирования данных об использовании
памяти непосредственно в продакшене. Примеры использования:
- обнаружение регрессии во время развертывания новой версии веб-страницы и фиксирования новых утечек памяти;
- прогон A/B-тестирования новой функции для оценки ее влияния на память и обнаружение утечек;
- корреляция использования памяти с продолжительностью сеанса;
- корреляция использования памяти с пользовательскими метриками для понимания общего влияния на память.
Совместимость браузеров
На момент написания материала API поддерживался только в Chrome 83 в качестве пробной версии. Результат работы API сильно зависит от реализации, поскольку браузеры имеют разные способы представления объектов в памяти и разные способы оценки ее использования. Браузеры могут исключить некоторые области памяти из учета, если надлежащий учет слишком затратен или неосуществим. Таким образом, результаты в разных браузерах сравнить не получится.
Использование performance.measureMemory()

Пробная версия позволит вам попробовать новые функции и дать обратную связь об их удобстве, практичности и эффективности сообществу веб-стандартов. Дополнительные сведения можно найти в гайде для веб-разработчиков. Чтобы использовать эту или другую пробную версию инструмента, посетите страницу регистрации.
Запросите токен и добавьте его на свои страницы. Есть два способа:
- Добавьте тег
origin-trial <meta>
, в head каждой страницы. Это может выглядеть примерно так:<meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">
- Если вы можете попасть на свой сервер, добавьте токен и результирующий заголовок ответа будет выглядеть примерно так:
Origin-Trial: TOKEN_GOES_HERE
Для того чтобы экспериментировать с
performance.measureMemory()
без «танцев» с пробной версией, активируйте флаг
#experimental-web-platform-features
в chrome://flags.
Некоторые особенности

Функция performance.measureMemory()
может завершиться ошибкой SecurityError,
если среда выполнения не удовлетворяет требованиям безопасности для
предотвращения cross-origin утечки информации. Чтобы этого избежать, инструмент требует наличие включенной изоляции сайта.
Веб-страница может использовать cross-origin изоляцию, установив заголовки COOP+COEP:
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);
}
Локальное тестирование
Chrome выполняет
измерение памяти во время сборки мусора. Это означает, что API не выдает результаты
незамедлительно – вместо этого он ожидает следующей сборки мусора. API провоцирует
сборку мусора после некоторого таймаута (сейчас это 20 секунд). Запустите
Chrome с флагом --enable-blink-features='ForceEagerMeasureMemory'
. Это уменьшит
тайм-аут до нуля и будет полезно для локальной отладки и тестирования.
Пример

Рекомендуемое использование API заключается в определении глобального монитора памяти, который проверяет использование памяти всей веб-страницы и отправляет результаты на сервер для агрегирования и анализа.
Самый простой способ – периодически делать выборку, например, каждые n минут. Однако это привёдет к смещению данных, поскольку скачки памяти могут возникать между выборками. В следующем примере показано, как выполнять измерения с помощью процесса Пуассона, который гарантирует, что выборки с одинаковой вероятностью будут происходить в любой момент времени (демо, источник).
Определите функцию,
которая планирует следующее измерение с помощью setTimeout()
с рандомным
интервалом. Функция должна быть вызвана после загрузки страницы.
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();
}
Функция
measurementInterval()
вычисляет рандомный интервал в миллисекундах таким
образом, что в среднем происходит одно измерение каждые пять минут. Изучите экспоненциальное распределение, если вас интересует матчасть, лежащая в основе
функции.
function measurementInterval() {
const MEAN_INTERVAL_IN_MS = 5 * 60 * 1000;
return -Math.log(Math.random()) * MEAN_INTERVAL_IN_MS;
}
Наконец, асинхронная
функция performMeasurement()
вызывает API, записывает результат и планирует
следующее измерение.
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();
}
Результат должен выглядеть примерно так:
{
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"]
}
]
}
Общая оценка использования памяти возвращается в байтах. Значение байтов определяется с помощью синтаксиса числового разделителя. Это значение зависит от реализации и не может быть сопоставлено между браузерами. Во время использования нашей origin trial версии значение несет в себе использование памяти главного окна и всех iframes того же сайта, плюс связанных с ними окон.
Список breakdown
содержит дополнительную информацию об используемой памяти. Каждая запись
описывает некоторую ее часть и приписывает ее набору окон, ifram-ов и воркеров,
идентифицируемых URL-адресами. В поле userAgentSpecificTypes
перечислены
конкретные для реализации типы, связанные с памятью.
Важно рассматривать все
списки в общем виде, а не основываться на конкретном браузере. Например, некоторые
браузеры могут возвращать пустой breakdown
или пустые атрибуты. Другие браузеры
могут возвращать несколько URL-адресов в атрибуте, указывая, что они не могут
различить, какой из этих URL-адресов владеет памятью.
Обратная связь

- Web Performance Community Group и команда Chrome хотели бы услышать ваши мысли на счет опыта работы с
performance.measureMemory()
. - Если в API есть недочеты или существуют недостающие свойства, которые вам необходимы – подайте запрос спецификации на performance.measureMemory или добавьте свои мысли к существующей проблеме.
- Вы нашли ошибку в реализации Chrome? Реализация отличается от спецификации? Подайте сообщение об ошибке по адресу new.crbug.com и обязательно включите как можно больше деталей, предоставьте инструкции по воспроизведению ошибки и установите компоненты в положение
Blink > PerformanceAPIs
. Glitch отлично подходит для этих целей. - Планируете ли вы использовать
performance.measureMemory()
? Ваша публичная поддержка поможет команде Chrome определять приоритеты и покажет другим разработчикам важность происходящего. Отправьте твит на @ChromiumDev и сообщите, где и как вы его используете.
Комментарии