24 / 36
Что такое Performance API в браузере?
Полный ответ
performance.now() возвращает время в миллисекундах с момента начала навигации:
JavaScript
// Базовое измерение времени выполнения
const start = performance.now();
// Какая-то операция
const data = heavyComputation();
const end = performance.now();
console.log(`Выполнение: ${(end - start).toFixed(2)} ms`);
// Почему не Date.now()?
// Date.now() зависит от системных часов -- они могут "прыгнуть"
// performance.now() монотонно растёт, не зависит от часов
User Timing API -- mark() и measure():
JavaScript
// mark() ставит именованную метку с timestamp
performance.mark('render-start');
renderApp();
performance.mark('render-end');
// measure() вычисляет разницу между метками
performance.measure('render-duration', 'render-start', 'render-end');
const measures = performance.getEntriesByName('render-duration');
console.log(`Рендер занял: ${measures[0].duration.toFixed(2)} ms`);
// Метки видны в DevTools (вкладка Performance, раздел Timings)
PerformanceObserver -- наблюдение за записями:
JavaScript
// Отслеживание всех пользовательских замеров
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(`${entry.name}: ${entry.duration.toFixed(2)} ms`);
}
});
observer.observe({ entryTypes: ['measure'] });
// Отслеживание загрузки ресурсов
const resourceObserver = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.transferSize > 100_000) {
console.warn(
`Тяжёлый ресурс: ${entry.name} (${(entry.transferSize / 1024).toFixed(0)} KB)`
);
}
}
});
resourceObserver.observe({ type: 'resource', buffered: true });
Полный набор доступных entry types:
JavaScript
// Типы записей, которые можно наблюдать:
// 'navigation' -- тайминг загрузки страницы
// 'resource' -- тайминг загрузки каждого ресурса
// 'paint' -- FP, FCP
// 'largest-contentful-paint' -- LCP
// 'first-input' -- FID
// 'layout-shift' -- CLS
// 'longtask' -- задачи длиннее 50 мс
// 'event' -- INP (задержка обработки событий)
// 'mark' -- пользовательские метки
// 'measure' -- пользовательские замеры
// Проверка поддержки
const supported = PerformanceObserver.supportedEntryTypes;
console.log(supported);
// ['element', 'event', 'first-input', 'largest-contentful-paint',
// 'layout-shift', 'longtask', 'mark', 'measure', 'navigation',
// 'paint', 'resource', 'visibility-state']
📌 Реальные кейсы
Измерение реальной производительности компонентов:
JavaScript
function measureComponent(name, fn) {
performance.mark(`${name}-start`);
const result = fn();
performance.mark(`${name}-end`);
performance.measure(name, `${name}-start`, `${name}-end`);
const entry = performance.getEntriesByName(name).pop();
if (entry && entry.duration > 16) { // больше одного кадра (60fps)
console.warn(`${name} занял ${entry.duration.toFixed(1)} ms -- тормозит рендер`);
}
// Очистка, чтобы не копились записи
performance.clearMarks(`${name}-start`);
performance.clearMarks(`${name}-end`);
performance.clearMeasures(name);
return result;
}
measureComponent('product-list-render', () => {
return renderProductList(products);
});
Отправка метрик в аналитику:
JavaScript
// Собираем ключевые метрики при загрузке страницы
window.addEventListener('load', () => {
// setTimeout чтобы метрики успели записаться
setTimeout(() => {
const navigation = performance.getEntriesByType('navigation')[0];
const paint = performance.getEntriesByName('first-contentful-paint')[0];
const metrics = {
dns: navigation.domainLookupEnd - navigation.domainLookupStart,
tcp: navigation.connectEnd - navigation.connectStart,
ttfb: navigation.responseStart - navigation.requestStart,
domReady: navigation.domContentLoadedEventEnd - navigation.startTime,
fullLoad: navigation.loadEventEnd - navigation.startTime,
fcp: paint ? paint.startTime : null,
resourceCount: performance.getEntriesByType('resource').length,
};
navigator.sendBeacon('/api/metrics', JSON.stringify(metrics));
}, 0);
});
Резюме
Performance API -- единственный надёжный способ измерять производительность в браузере. performance.now() точнее Date.now(), mark()/measure() позволяют замерять любые участки кода, а PerformanceObserver отслеживает метрики в реальном времени. Все данные видны в DevTools на вкладке Performance.