Как 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
,
Есть несколько блогов с некоторой информацией об общих проблемах и способах обратного отслеживания:
- http://eli.thegreenplace.net/2015/programmatic-access-to-the-call-stack-in-c/ - локальная трассировка с помощью libunwind
- http://codingrelic.geekhold.com/2009/05/pre-mortem-backtracing.html gcc's
__builtin_return_address(N)
против Глибаbacktrace()
против локальной трассировки libunwind - http://lucumr.pocoo.org/2014/10/30/dont-panic/ отследить и раскрутить в ржавчине
- https://github.com/gperftools/gperftools/wiki/gperftools '-stacktrace-capturing-методы-и-их-проблемы та же проблема обратного отслеживания в библиотеке профилировщика на основе программного таймера gperftools
Карликовая поддержка perf_events
/ perf
:
- https://lwn.net/Articles/499116/ [RFCv4 00/16] perf: добавление backtrace post dwarf unwind, May 2012
- https://lwn.net/Articles/507753/ [PATCHv7 00/17] perf: добавление обратной трассировки после раскрутки гномов, июль 2012
- https://wiki.linaro.org/LEG/Engineering/TOOLS/perf-callstack-unwinding - раскручивание гнома на ARM 7/8 для перфорации
- https://wiki.linaro.org/KenWerner/Sandbox/libunwind - тоже не карликовые методы