Как измерять производительность JavaScript
Проблемы с производительностью JavaScript легко почувствовать, но сложно локализовать. Ваше приложение работает медленно, взаимодействия запаздывают, пользователи это замечают — но без правильных инструментов измерения вы действуете наугад. Эта статья охватывает практические техники измерения производительности JavaScript с использованием современных браузерных API и DevTools, чтобы вы могли находить реальные узкие места и исправлять то, что действительно важно.
Ключевые выводы
- Различайте синтетическое (лабораторное) тестирование и мониторинг реальных пользователей (RUM) — используйте лабораторные инструменты для диагностики, полевые данные для валидации.
- Панель Performance в Chrome DevTools показывает длительные задачи, flame charts и деревья вызовов для детального профилирования.
- Performance API (
performance.now(),performance.mark(),performance.measure()) обеспечивает точное программное измерение времени с интеграцией в DevTools. PerformanceObserverавтоматизирует сбор записей для продакшн-мониторинга, включая обнаружение длительных задач.- Interaction to Next Paint (INP) — это Core Web Vital, наиболее тесно связанный с отзывчивостью. Выполнение JavaScript является основным фактором, наряду с работой по стилизации, компоновке и отрисовке.
Лабораторное тестирование vs. данные реальных пользователей
Прежде чем браться за инструмент, поймите два типа измерения производительности JavaScript:
- Синтетическое (лабораторное) тестирование запускает ваш код в контролируемой среде. Инструменты вроде Lighthouse и Chrome DevTools дают вам повторяемые, отлаживаемые результаты. Отлично подходят для разработки и CI-пайплайнов.
- Полевые данные (RUM) фиксируют то, что испытывают реальные пользователи. Инструменты вроде Chrome User Experience Report (CrUX) или RUM-платформы показывают вам фактическую производительность на разных устройствах и в разных сетях.
Используйте лабораторные инструменты для диагностики проблем. Используйте полевые данные для подтверждения их важности.
Профилирование JavaScript в Chrome DevTools
Chrome DevTools — это наиболее практичная отправная точка для метрик производительности JavaScript. Откройте панель Performance, нажмите запись, взаимодействуйте со страницей, затем остановите запись.
На что обращать внимание:
- Long Tasks — любая задача, блокирующая главный поток более чем на 50 мс, отображается красным цветом. Они часто задерживают взаимодействия пользователя. Современные инструменты также могут показывать Long Animation Frames, которые предоставляют более детальную информацию о медленных кадрах, влияющих на отзывчивость.
- Call Tree / Bottom-Up views — определяют, какие функции потребляют больше всего времени выполнения.
- Flame chart — визуализирует стек вызовов во времени, чтобы выявить затратную синхронную работу.
Firefox DevTools предлагает похожий профайлер. Оба инструмента бесплатны, не требуют настройки и работают на любом сайте.
Измерение времени выполнения JavaScript с помощью Performance API
Для точного программного измерения производительности JavaScript используйте встроенный в браузер Performance API.
Использование performance.now()
performance.now() возвращает временную метку высокого разрешения в миллисекундах относительно момента создания страницы — что делает его более надежным, чем Date.now(), для измерения времени выполнения кода.
const start = performance.now()
runExpensiveOperation()
const duration = performance.now() - start
console.log(`Took ${duration}ms`)
Использование performance.mark() и performance.measure()
Для структурированного измерения времени в нескольких точках используйте метки и измерения. Это напрямую интегрируется с DevTools и PerformanceObserver.
performance.mark('fetch-start')
const data = await fetchData()
performance.mark('fetch-end')
const measure = performance.measure('fetch-duration', 'fetch-start', 'fetch-end')
console.log(measure.duration) // миллисекунды
Измерения появляются на панели Performance в Chrome DevTools в треке Timings, что упрощает их корреляцию с другой активностью на главном потоке.
Discover how at OpenReplay.com.
Автоматизация измерений с помощью PerformanceObserver
PerformanceObserver позволяет реагировать на записи производительности по мере их появления — полезно для продакшн-мониторинга.
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(entry.name, entry.duration)
}
})
observer.observe({ type: 'measure', buffered: true })
Вы также можете наблюдать за записями longtask, чтобы обнаруживать блокировку главного потока в реальных пользовательских сессиях.
Core Web Vitals и INP: метрики, которые имеют значение
Core Web Vitals от Google — это стандартные метрики производительности JavaScript для пользовательского опыта. Наиболее релевантная для JavaScript — это Interaction to Next Paint (INP) — она измеряет задержку всех взаимодействий (клики, касания, ввод с клавиатуры) на протяжении всего времени жизни страницы.
INP выше 200 мс — это предупреждающий знак. Выше 500 мс — плохо. Интенсивное выполнение JavaScript во время обработчиков событий — наиболее частая причина.
Используйте библиотеку web-vitals для измерения INP в полевых условиях:
import { onINP } from 'web-vitals'
onINP(({ value }) => console.log('INP:', value))
Для SPA учтите, что мягкие навигации (смена маршрутов без полной перезагрузки страницы) лишь частично фиксируются стандартными метриками навигации. Браузерная поддержка измерения мягких навигаций всё ещё развивается, поэтому ручная инструментация переходов между маршрутами с помощью performance.mark() может помочь заполнить пробелы.
Выбор правильного инструмента
| Цель | Инструмент |
|---|---|
| Быстрая отладка | console.time() / console.timeEnd() |
| Точное измерение времени | performance.now() |
| Структурированное визуальное измерение | performance.mark() + performance.measure() |
| Автоматизированный мониторинг | PerformanceObserver |
| Полное профилирование страницы | Панель Performance в Chrome DevTools |
| Оценки аудита + полевые данные | Lighthouse + CrUX |
Заключение
Эффективное измерение производительности JavaScript начинается с правильного инструмента для правильного вопроса. Используйте DevTools для профилирования и исследования, Performance API для инструментирования конкретных путей кода, и Core Web Vitals — особенно INP — чтобы понять, что на самом деле испытывают пользователи. Сначала измеряйте, затем оптимизируйте.
Часто задаваемые вопросы
performance.now() возвращает временную метку высокого разрешения относительно момента создания страницы, обеспечивая точность до долей миллисекунды. Date.now() опирается на системные часы, которые могут подвергаться корректировкам времени, и предлагает точность только до миллисекунды. Для бенчмаркинга выполнения кода performance.now() является более точным и надёжным выбором.
Используйте PerformanceObserver, настроенный на наблюдение за записями типа longtask. Любая задача, превышающая 50 мс на главном потоке, помечается как длительная задача. Собирая эти записи в продакшене, вы можете определить, какие пользовательские взаимодействия вызывают блокирующую работу, и расставить приоритеты оптимизации там, где это действительно важно.
Interaction to Next Paint измеряет задержку всех взаимодействий во время посещения страницы и сообщает о худшем из них. First Input Delay фиксировал только задержку самого первого взаимодействия. INP даёт более полную картину отзывчивости во время выполнения, поэтому Google заменил FID на INP в качестве Core Web Vital в марте 2024 года.
Да. Разместите вызовы performance.mark() до и после вашего выражения await, затем вызовите performance.measure() с обоими именами меток, чтобы вычислить прошедшее время. Полученная запись измерения включает полную продолжительность асинхронной операции и появляется в треке Timings в DevTools для визуальной корреляции.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.