Перейти к содержимому
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.

Что такое Performance API в браузере? | JScriptiser