Как Perf-утилита Linux понимает следы стека?

Perf-утилита для Linux отлично используется Бренданом Греггом для генерации пламенных графиков для c/ C++, кода jvm, кода nodejs и т. Д.

Ядро Linux понимает трассировку стека? Где я могу прочитать больше о том, как инструмент может анализировать следы процессов в стеке, даже если процессы написаны на совершенно разных языках?

1 ответ

Решение

Краткое описание трассировки стека perf Грегг: http://www.brendangregg.com/perf.html

4.4 трассировки стека

Всегда компилируйте с указателями кадра. Пропуск указателей фреймов - это злая оптимизация компилятора, которая ломает отладчики, и, к сожалению, часто используется по умолчанию. Без них вы можете увидеть неполные стеки из perf_events... Есть два способа исправить это: либо использовать данные дварфа для размотки стека, либо вернуть указатели фреймов.

карликовый

Начиная с ядра 3.9, perf_events поддерживает обходной путь для отсутствующих указателей фреймов в стеках пользовательского уровня: libunwind, который использует dwarf. Это можно включить с помощью "-g dwarf". ... оптимизация компилятора (-O2), который в этом случае пропустил указатель кадра.... перекомпилировать.. с -fno-omit-frame-pointer:

Языки не в стиле C могут иметь другой формат фрейма или могут не указывать фреймы:

4,3. Символы JIT (Java, Node.js)

Программы, которые имеют виртуальные машины (ВМ), такие как Java JVM и узел v8, выполняют свой собственный виртуальный процессор, который имеет свой собственный способ выполнения функций и управления стеками. Если вы профилируете их с помощью perf_events, вы увидите символы для движка виртуальной машины. Perf_events имеет поддержку JIT для решения этой проблемы, которая требует от виртуальной машины поддерживать /tmp/perf-PID.map файл для перевода символов.

Обратите внимание, что Java может не отображать полные стеки для начала, из-за того, что в точке доступа x86 пропущен указатель кадра (как в gcc). В более новых версиях (JDK 8u60+) вы можете использовать -XX:+PreserveFramePointer возможность исправить это поведение,...

Сообщение Gregg в блоге о Java и трассировке стека: http://techblog.netflix.com/2015/07/java-in-flames.html ("Исправление указателей фреймов" - исправлено в некоторых версиях JDK8 и в JDK9 путем добавления опции в запуск программы)

Теперь ваши вопросы:

Как Perf-утилита Linux понимает следы стека?

perf Утилита в основном (в ранних версиях) просто анализирует данные, возвращенные из подсистемы ядра Linux " perf_events "(или иногда" events ") доступ к syscall perf_event_open, Для трассировки стека вызовов есть опции PERF_SAMPLE_CALLCHAIN / PERF_SAMPLE_STACK_USER:

sample_type PERF_SAMPLE_CALLCHAIN ​​Записывает цепочку вызовов (обратная трассировка стека).

          PERF_SAMPLE_STACK_USER (since Linux 3.7)
                 Records the user level stack, allowing stack unwinding.

Ядро Linux понимает трассировку стека?

Это может понять (если реализовано) и не может, в зависимости от вашей архитектуры процессора. Функция выборки (получение / чтение стека вызовов из живого процесса) в независимой от архитектуры части ядра определяется как __weak с пустым телом:

http://lxr.free-electrons.com/source/kernel/events/callchain.c?v=4.4#L26

 27 __weak void perf_callchain_kernel(struct perf_callchain_entry *entry,
 28                                   struct pt_regs *regs)
 29 {
 30 }
 31 
 32 __weak void perf_callchain_user(struct perf_callchain_entry *entry,
 33                                 struct pt_regs *regs)
 34 {
 35 }

В 4.4 сэмплер callchain пользовательского пространства ядра переопределен в зависящей от архитектуры части ядра для x86 / x86_64, ARC, SPARC, ARM / ARM64, Xtensa, Tilera TILE, PowerPC, Imagination Meta:

http://lxr.free-electrons.com/ident?v=4.4;i=perf_callchain_user

arch/x86/kernel/cpu/perf_event.c, line 2279
arch/arc/kernel/perf_event.c, line 72
arch/sparc/kernel/perf_event.c, line 1829
arch/arm/kernel/perf_callchain.c, line 62
arch/xtensa/kernel/perf_event.c, line 339
arch/tile/kernel/perf_event.c, line 995
arch/arm64/kernel/perf_callchain.c, line 109
arch/powerpc/perf/callchain.c, line 490
arch/metag/kernel/perf_callchain.c, line 59

Чтение цепочки вызовов из пользовательского стека может быть нетривиальным для некоторых архитектур и / или для некоторых режимов.

Какую архитектуру процессора вы используете? Какие языки и ВМ используются?

Где я могу прочитать больше о том, как инструмент может анализировать следы процессов в стеке, даже если процессы написаны на совершенно разных языках?

Вы можете попробовать gdb и / или отладчики для языка или backtrace функция libc или поддержка раскручивания только для чтения в libunwind (в libunwind есть пример локальной трассировки, show_backtrace()).

Они могут иметь лучшую поддержку разбора кадров / лучшую интеграцию с виртуальной машиной языка или с информацией раскрутки. Если GDB (с backtrace команда) или другие отладчики не могут получить трассировку стека от работающей программы, может вообще не быть возможности получить трассировку стека.

Если они могут получить трассировку вызова, но perf не может (даже после перекомпиляции с -fno-omit-frame-pointer для C/C++) можно добавить поддержку такой комбинации формата архитектура + фрейм в perf_events а также perf,

Есть несколько блогов с некоторой информацией об общих проблемах и способах обратного отслеживания:

Карликовая поддержка perf_events / perf:

Другие вопросы по тегам