Как использовать инструмент linux `perf` для создания профиля "Off-CPU"
Брендан Д. Грегг (автор книги DTrace) имеет интересный вариант профилирования: "Off-CPU" профилирование (и График пламени вне процессора; слайды 2013, p112-137), чтобы увидеть, где поток или приложение были заблокированы (не были выполнены процессором, но ожидали ввода/вывода, обработчика страницы или отказались из-за нехватки ресурсов ЦП):
На этот раз показано, какие кодовые пути заблокированы и ждут во время работы вне CPU, и как долго точно. Это отличается от традиционного профилирования, которое часто отображает активность потоков в заданный интервал и (обычно) рассматривает только потоки, если они выполняют работу с процессором.
Он также может объединять данные профиля вне CPU и профиль On-CPU вместе: http://www.brendangregg.com/FlameGraphs/hotcoldflamegraphs.html
Примеры, приведенные Греггом, выполняются с помощью dtrace
, который обычно не доступен в ОС Linux. Но есть некоторые аналогичные инструменты (ktap, systemtap, perf) и perf
, как я думаю, имеет самую широкую установленную базу. Обычно perf
генерируются профили On-CPU (какие функции выполнялись чаще всего на CPU).
- Как перевести примеры Gregg Off-CPU в инструмент
perf
для профилирования в Linux?
PS: Существует ссылка на вариант systemtap плагинов вне CPU на слайдах из LISA13, p124: "Ичунь Чжан создал их и использует их в Linux с помощью SystemTap для сбора профильных данных. См.: http://agentzh.org/misc/slides/off-cpu-flame-graphs.pdf" "(Встреча с пивом CloudFlare 23 августа 2013 года)
Ответы
Ответ 1
Первой техникой, которую я опубликовал [1], было обходное решение с большими накладными расходами, до тех пор, пока у исполнителя не будет поддержки BPF для этого.
В настоящее время самый дешевый способ создания графика пламени вне процессора в Linux находится на ядре 4.6+ (у которого есть поддержка трассировки стека BPF) и с ОЦК/БПФ. Я написал для него инструмент offcputime [2], который можно запустить с опцией -f для "сложенного вывода", подходящей для подачи на пламя .pl. Этот инструмент offcputime выполняет подсчет времени и стека в содержимом ядра и сбрасывает отчет, который затем печатается с символами.
В один прекрасный день я ожидаю, что сам perf также сможет это сделать: запустите программу BPF, которая выполняет подсчет в ядре и сбросит отчет.
В то же время мы можем использовать bcc/BPF. Если по какой-то причине вы не можете использовать bcc, вы можете прямо сейчас взять эту программу offcputime и записать ее на C. Более сложная версия доступна в источнике Linux, например sample/bpf/offwaketime *. С новыми функциями BPF в Linux, если есть желание, есть способ.
[1] http://www.brendangregg.com/blog/2015-02-26/linux-perf-off-cpu-flame-graph.html
[2] https://github.com/iovisor/bcc/blob/master/tools/offcputime_example.txt
Ответ 2
Брендан Грегг опубликовал инструкцию о генерации пламени Off-cpu:
http://www.brendangregg.com/blog/2015-02-26/linux-perf-off-cpu-flame-graph.html
и https://github.com/brendangregg/FlameGraph/issues/47#
Графики пламени времени вне процессора могут решить (скажем) 60% проблем, а оставшаяся часть требует прокрутки потоков, чтобы найти основную причину. Я объяснил графики пламени вне процессора, эту проблему пробуждения и дополнительную работу в моем разговоре LISA13 на графиках пламени (slides, youtube).
Здесь я покажу один способ сделать графики пламени времени вне процессора, используя Linux perf_events.
# perf record -e sched:sched_stat_sleep -e sched:sched_switch \
-e sched:sched_process_exit -a -g -o perf.data.raw sleep 1
# perf inject -v -s -i perf.data.raw -o perf.data
# perf script -f comm,pid,tid,cpu,time,period,event,ip,sym,dso,trace | awk '
NF > 4 { exec = $1; period_ms = int($5 / 1000000) }
NF > 1 && NF <= 4 && period_ms > 0 { print $2 }
NF < 2 && period_ms > 0 { printf "%s\n%d\n\n", exec, period_ms }' | \
./stackcollapse.pl | \
./flamegraph.pl --countname=ms --title="Off-CPU Time Flame Graph" --colors=io > offcpu.svg
stackcollapse.pl и flamegraph.pl из Gregg используются для рисования пламени.
Существуют первоочередные опции, используемые из ядер 3.17 и новее...