← Назад к вопросам

Как измерять Performance внутри браузера?

1.0 Junior🔥 221 комментариев
#Браузер и сетевые технологии

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Измерение Performance в браузере

Performance — критически важный метрик для веб-приложений. Браузер предоставляет множество встроенных API для измерения различных аспектов производительности: времени загрузки, выполнения кода, рендеринга и взаимодействия пользователя.

Performance API - основные методы

// Основные Web Vitals
const perfData = performance.getEntriesByType('navigation')[0];

console.log('DNS lookup:', perfData.domainLookupEnd - perfData.domainLookupStart);
console.log('TCP connection:', perfData.connectEnd - perfData.connectStart);
console.log('Time to First Byte:', perfData.responseStart - perfData.requestStart);
console.log('DOMContentLoaded:', perfData.domContentLoadedEventEnd - perfData.domContentLoadedEventStart);
console.log('Load event:', perfData.loadEventEnd - perfData.loadEventStart);

// Всё время загрузки
console.log('Полное время загрузки:', perfData.loadEventEnd - perfData.fetchStart);

Web Vitals - метрики, которые гугл учитывает для SEO

Largest Contentful Paint (LCP) — время отрисовки самого большого контента:

const observer = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lastEntry = entries[entries.length - 1];
  console.log('LCP:', lastEntry.renderTime || lastEntry.loadTime);
});

observer.observe({ entryTypes: ['largest-contentful-paint'] });

// Хорошее значение: менее 2.5 секунд

First Input Delay (FID) — задержка первого взаимодействия пользователя:

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log('FID:', entry.processingDuration);
  }
});

observer.observe({ entryTypes: ['first-input'] });

// Хорошее значение: менее 100ms

Cumulative Layout Shift (CLS) — неожиданные сдвиги элементов:

let clsScore = 0;

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (!entry.hadRecentInput) {
      clsScore += entry.value;
      console.log('CLS score:', clsScore);
    }
  }
});

observer.observe({ entryTypes: ['layout-shift'] });

// Хорошее значение: менее 0.1

Timing API - измерение кастомных операций

// Старт измерения операции
performance.mark('operation-start');

// ... выполняем операцию
for (let i = 0; i < 1000000; i++) {
  Math.sqrt(i);
}

// Конец измерения
performance.mark('operation-end');

// Измерить разницу
performance.measure('my-operation', 'operation-start', 'operation-end');

// Получить результат
const measure = performance.getEntriesByName('my-operation')[0];
console.log('Время операции:', measure.duration, 'ms');

Практический пример с интернет-запросом:

async function fetchData(url) {
  performance.mark('fetch-start');
  
  try {
    const response = await fetch(url);
    const data = await response.json();
    
    performance.mark('fetch-end');
    performance.measure('fetch-time', 'fetch-start', 'fetch-end');
    
    const measure = performance.getEntriesByName('fetch-time')[0];
    console.log(`Fetch занял ${measure.duration.toFixed(2)}ms`);
    
    return data;
  } catch (error) {
    console.error('Fetch failed:', error);
  }
}

Измерение времени выполнения функции

function measurePerformance(fn, label = 'Operation') {
  const start = performance.now();
  const result = fn();
  const end = performance.now();
  console.log(`${label}: ${(end - start).toFixed(2)}ms`);
  return result;
}

// Использование
measurePerformance(() => {
  let sum = 0;
  for (let i = 0; i < 10000000; i++) {
    sum += i;
  }
  return sum;
}, 'BigLoop');

// Или для асинхронных функций
async function measureAsync(fn, label = 'Async Operation') {
  const start = performance.now();
  const result = await fn();
  const end = performance.now();
  console.log(`${label}: ${(end - start).toFixed(2)}ms`);
  return result;
}

PerformanceObserver - мониторинг различных метрик

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log('Entry:', entry);
  }
});

// Слушать несколько типов метрик
observer.observe({
  entryTypes: ['navigation', 'paint', 'resource', 'measure']
});

// Очистить
observer.disconnect();

Отслеживание загрузки ресурсов:

const observer = new PerformanceObserver((list) => {
  const resources = list.getEntries();
  
  resources.forEach(resource => {
    if (resource.duration > 1000) {
      console.warn('Медленный ресурс:', {
        name: resource.name,
        duration: resource.duration,
        size: resource.transferSize
      });
    }
  });
});

observer.observe({ entryTypes: ['resource'] });

Memory API - потребление памяти

// Доступно только в Chrome, с флагом --enable-precise-memory-info
if (performance.memory) {
  console.log('Используется памяти:', Math.round(performance.memory.usedJSHeapSize / 1048576), 'MB');
  console.log('Лимит памяти:', Math.round(performance.memory.jsHeapSizeLimit / 1048576), 'MB');
  console.log('Процент использования:', 
    (performance.memory.usedJSHeapSize / performance.memory.jsHeapSizeLimit * 100).toFixed(1), '%'
  );
}

// Мониторинг памяти
setInterval(() => {
  if (performance.memory) {
    const used = Math.round(performance.memory.usedJSHeapSize / 1048576);
    const limit = Math.round(performance.memory.jsHeapSizeLimit / 1048576);
    console.log(`Memory: ${used}MB / ${limit}MB`);
  }
}, 5000);

Paint Timing - моменты отрисовки

// First Paint - момент первой отрисовки
// First Contentful Paint - момент отрисовки первого контента

const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log(`${entry.name}: ${entry.startTime.toFixed(2)}ms`);
  }
});

observer.observe({ entryTypes: ['paint'] });

Navigation Timing - подробная информация о загрузке

function getNavigationTiming() {
  const navigation = performance.getEntriesByType('navigation')[0];
  
  return {
    'DNS': navigation.domainLookupEnd - navigation.domainLookupStart,
    'TCP': navigation.connectEnd - navigation.connectStart,
    'TLS': navigation.secureConnectionStart > 0 
      ? navigation.connectEnd - navigation.secureConnectionStart 
      : 0,
    'Request': navigation.responseStart - navigation.requestStart,
    'Response': navigation.responseEnd - navigation.responseStart,
    'DOM Processing': navigation.domInteractive - navigation.domLoading,
    'DOM Content Loaded': navigation.domContentLoadedEventEnd - navigation.domContentLoadedEventStart,
    'Page Load': navigation.loadEventEnd - navigation.loadEventStart
  };
}

console.table(getNavigationTiming());

Практический пример: собственная библиотека метрик

class MetricsCollector {
  constructor() {
    this.metrics = {};
  }

  start(label) {
    performance.mark(`${label}-start`);
  }

  end(label) {
    performance.mark(`${label}-end`);
    performance.measure(label, `${label}-start`, `${label}-end`);
    const measure = performance.getEntriesByName(label)[0];
    this.metrics[label] = measure.duration;
    return measure.duration;
  }

  report() {
    console.table(this.metrics);
  }

  clear() {
    this.metrics = {};
    performance.clearMarks();
    performance.clearMeasures();
  }
}

// Использование
const collector = new MetricsCollector();

collector.start('api-call');
await fetch('/api/data');
console.log('API call took:', collector.end('api-call'), 'ms');

collector.report();

Core Web Vitals - рекомендуемые значения

МетрикаХорошоТребует улучшенияПлохо
LCP< 2.5s2.5s - 4s> 4s
FID< 100ms100ms - 300ms> 300ms
CLS< 0.10.1 - 0.25> 0.25

Инструменты для анализа

// Google Web Vitals библиотека
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';

getCLS(console.log);
getFID(console.log);
getFCP(console.log);
getLCP(console.log);
getTTFB(console.log);

Выводы

  • Используй Performance API для измерения кастомных операций
  • Мониторь Web Vitals для SEO и UX
  • PerformanceObserver помогает отслеживать автоматически
  • Chrome DevTools Performance tab для детального анализа
  • Регулярно проверяй память и рендеринг
  • Оптимизируй метрики, которые видит пользователь