Профилирование JS:
увидеть самое важное и не утонуть в море чисел

Виктор Хомяков, Яндекс

Профилирование JS:
увидеть самое важное и не утонуть в море чисел

Logo

Виктор Хомяков, Яндекс

О себе

Я профессионально занимаюсь анализом и улучшением производительности страницы поиска в Яндексе (Search Engine Result Page, он же SERP или просто серп).

Виктор Хомяков
SERP sample

https://ru.wikipedia.org/wiki/Яндекс#Статистика_и_финансовые_показатели

Профилирование: высокий порог входа

JS Profiler Tree
JS Profiler Flame Chart

О чём я хочу рассказать

Если у меня
React

React на серпе Яндекса

SERP React sample
React Performance

Сборки React DOM

https://github.com/facebook/react/blob/master/packages/react-dom

Было

SERP React Performance zoomed

Стало

SERP React Dev Performance zoomed
SERP React Dev Performance zoomed

Профилирование компонентов React

Если у меня
нет React

console.timeStamp('Начало inline JS');
console.timeStamp

На одной шкале с DOMContentLoaded и load

DOMContentLoaded
console.time(label); /* код */ console.timeEnd(label);
console.time
performance.mark(markName); /* код */ performance.measure(label, markName);
performance.measure

Несколько особенностей

Материалы

Если я
в танке в Node.js

Node.js Profiler

В инспекторе для Node.js нет вкладки Performance, есть только Profiler

Developer Tools for Node.js

Много чисел — опять неинтересно

Node.js Profiler Tree

Но есть JS Flame Chart

Node.js Profiler Flame Chart

Chrome: изучение участка кода

1. Оборачиваем код

console.profile();
// код
console.profileEnd();
        

2. Записываем и сохраняем профайлы

3. Мержим профайлы

github.com/victor-homyakov/merge-cpuprofiles

merge-cpuprofiles repository on GitHub

4. Анализируем объединённый профайл

Merged profiles

Материалы

Хочу свои таймлайны

1a. Оборачиваем код в замеры времени в Node.js

// точка отсчёта - загрузка модуля
const initialOffset = process.hrtime(), events = [];
// время, прошедшее с момента initialOffset
let start = process.hrtime(initialOffset);
// код
let end = process.hrtime(initialOffset);
events.push(['имя метода', start, end]);
        

1b. Оборачиваем код в замеры времени в браузере

const events = [];
// точка отсчёта - начало навигации
let start = performance.now();
// код
let end = performance.now();
events.push(['имя метода', start, end]);
        

2. Собираем данные и сохраняем JSON

fs.writeFileSync(
    `timeline-${Date.now()}.json`,
    JSON.stringify(events)
);
    

3. Берём Timeline из Google Charts

Документация

Google Charts Timeline

4. Рисуем свои данные

Демо

Google Charts Timeline demo

Хочу таймлайны, не хочу писать код

1. Собираем данные в формате Trace Event

const traceEvents = [];
traceEvents.push({
    pid: 1, tid: 1, ph: 'X', name: 'имя метода',
    ts: startMicroseconds, dur: durationMicroseconds,
    args: { // любая детальная информация
        name: 'имя метода',
        ms: durationMicroseconds / 1000
    }
});
        

2. Сохраняем в JSON

fs.writeFileSync(
    `trace-${Date.now()}.json`,
    JSON.stringify({
        traceEvents,
        metaInfoCreated: new Date()
    })
);
        

3. Открываем в chrome://tracing

Другие варианты названия: browser://tracing, about:tracing

chrome://tracing
chrome://tracing

Материалы

Заключение

Спасибо! Вопросы?

Виктор Хомяков

разработчик интерфейсов