Перейти к основному содержимому

Интеграция V8 с инструментом Linux `perf`

V8 имеет встроенную поддержку инструмента Linux perf. Она активируется с помощью опции командной строки --perf-prof. V8 записывает данные о производительности во время выполнения в файл, который можно использовать для анализа производительности JIT-кода V8 (включая имена JS-функций) с помощью инструмента Linux perf.

Требования

  • Версия linux-perf 5 или выше (предыдущие версии не поддерживают JIT). (См. инструкцию в конце)
  • Сборка V8/Chrome с использованием enable_profiling=true для более точных символов C++.

Сборка V8

Чтобы использовать интеграцию V8 с Linux perf, вам нужно собрать его с флагом gn enable_profiling = true:

echo 'enable_profiling = true' >> out/x64.release/args.gn
autoninja -C out/x64.release

Профилирование d8 с помощью linux-perf-d8.py

После сборки d8 вы можете начать использовать Linux perf:

tools/profiling/linux-perf-d8.py out/x64.release/d8 path/to/test.js;

Более полный пример:

echo '(function f() {
var s = 0; for (var i = 0; i < 1000000000; i++) { s += i; } return s;
})();' > test.js;

# Используйте пользовательские флаги V8 и отдельную директорию для вывода для уменьшения беспорядка:
mkdir perf_results
tools/profiling/linux-perf-d8.py --perf-data-dir=perf_results \
out/x64.release/d8 --expose-gc --allow-natives-syntax test.js;

# Красивый пользовательский интерфейс (`-flame` доступен только для Google, используйте `-web` как публичную альтернативу):
pprof -flame perf_results/XXX_perf.data.jitted;
# Инструмент для терминала:
perf report -i perf_results/XXX_perf.data.jitted;

Просмотрите linux-perf-d8.py --help для получения дополнительных деталей. Обратите внимание, что вы можете использовать все флаги d8 после аргумента бинарного файла d8.

Профилирование Chrome или content_shell с помощью linux-perf-chrome.py

  1. Вы можете использовать скрипт linux-perf-chrome.py для профилирования Chrome. Убедитесь, что вы добавили необходимые флаги gn для Chrome, чтобы получить корректные символы C++.

  2. После завершения сборки вы можете профилировать веб-сайт с полными символами для C++ и JS-кода.

    mkdir perf_results;
    tools/profiling/linux-perf-chrome.py out/x64.release/chrome \
    --perf-data-dir=perf_results --timeout=30
  3. Перейдите на свой веб-сайт и затем закройте браузер (или подождите завершения --timeout)

  4. После выхода из браузера linux-perf.py выполнит постобработку файлов и покажет список с результатами для каждого процесса рендерера:

    chrome_renderer_1583105_3.perf.data.jitted      19.79MiB
    chrome_renderer_1583105_2.perf.data.jitted 8.59MiB
    chrome_renderer_1583105_4.perf.data.jitted 0.18MiB
    chrome_renderer_1583105_1.perf.data.jitted 0.16MiB

Исследование результатов linux-perf

Наконец, вы можете использовать инструмент Linux perf для исследования профиля процесса рендерера d8 или Chrome:

perf report -i perf_results/XXX_perf.data.jitted

Вы также можете использовать pprof для генерации дополнительных визуализаций:

# Примечание: `-flame` доступно только для Google, используйте `-web` как публичную альтернативу:
pprof -flame perf_results/XXX_perf.data.jitted;

Низкоуровневое использование linux-perf

Использование linux-perf напрямую с d8

В зависимости от вашего сценария использования, возможно, вам потребуется использовать linux-perf напрямую с d8. Это требует двухэтапного процесса: сначала perf record создает файл perf.data, который должен быть обработан с помощью perf inject для добавления JS-символов.

perf record --call-graph=fp --clockid=mono --freq=max \
--output=perf.data
out/x64.release/d8 \
--perf-prof --no-write-protect-code-memory \
--interpreted-frames-native-stack \
test.js;
perf inject --jit --input=perf.data --output=perf.data.jitted;
perf report --input=perf.data.jitted;

Флаги linux-perf для V8

--perf-prof используется в командной строке V8 для записи выборок производительности в JIT-коде.

--nowrite-protect-code-memory требуется для отключения защиты записи в памяти кода. Это необходимо, потому что perf отбрасывает информацию о страницах кода при событии удаления бита записи из страницы кода. Вот пример, который записывает выборки из тестового файла JavaScript:

--interpreted-frames-native-stack используется для создания различных точек входа (скопированных версий InterpreterEntryTrampoline) для интерпретируемых функций, чтобы их можно было различать с помощью perf только по адресу. Поскольку InterpreterEntryTrampoline должен быть скопирован, это приводит к небольшому снижению производительности и увеличению использования памяти.

Использование linux-perf с chrome напрямую

  1. Вы можете использовать те же флаги V8 для профилирования самого chrome. Следуйте инструкциям выше для правильных флагов V8 и добавьте требуемые флаги gn для chrome в вашу сборку chrome.

  2. После того как сборка будет готова, вы можете профилировать веб-сайт с полными символами для C++ и JS кода.

    out/x64.release/chrome \
    --user-data-dir=`mktemp -d` \
    --no-sandbox --incognito --enable-benchmarking \
    --js-flags='--perf-prof --no-write-protect-code-memory --interpreted-frames-native-stack'
  3. После запуска chrome найдите id процесса рендерера с помощью диспетчера задач, и используйте его для начала профилирования:

    perf record -g -k mono -p $RENDERER_PID -o perf.data
  4. Перейдите на ваш веб-сайт, а затем продолжайте следовать следующему разделу о том, как оценить вывод perf.

  5. После завершения выполнения объедините статическую информацию, собранную инструментом perf, с образцами производительности, выведенными V8 для JIT-кода:

    perf inject --jit --input=perf.data --output=perf.data.jitted
  6. Наконец, вы можете использовать инструмент Linux perf для исследования

Сборка perf

Если у вас устаревшее ядро Linux, вы можете локально собрать linux-perf с поддержкой jit.

  • Установите новое ядро Linux, а затем перезагрузите компьютер:

     sudo apt-get install linux-generic-lts-wily;
  • Установите зависимости:

    sudo apt-get install libdw-dev libunwind8-dev systemtap-sdt-dev libaudit-dev \
    libslang2-dev binutils-dev liblzma-dev;
  • Скачайте исходные коды ядра, включающие последние исходные коды инструмента perf:

    cd some/directory;
    git clone --depth 1 git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git;
    cd tip/tools/perf;
    make

На следующих этапах вызывайте perf как some/director/tip/tools/perf/perf.