freebsd-pmcstat/

Ранее в заметке Профилирование кода на C/C++ в Linux и FreeBSD вскользь упоминалось, что аналогом perf из мира Linux во FreeBSD является утилита pmcstat. Однако не сообщалось, как именно этим pmcstat пользоваться, просто потому что на тот момент я этого и не умел. Не так давно, благодаря помощи со стороны Федора Сигаева , мне все-таки удалось осилить pmcstat. А теперь, благодаря помощи с моей стороны, осилить удастся и вам!

Примечания: (1) Также вас могут заинтересовать статьи Использование DTrace на примере FreeBSD и Linux , Установка и простые примеры использования SystemTap и Трассировка и профайлинг в Linux с помощью bcc/eBPF . (2) Насколько мне известно, в MacOS утилиты pmcstat нет.

По традиции, сначала немного матчасти. Performance Monitoring Counters, или PMC, называют набор регистров специального назначения, встроенный в современные CPU для хранения счетчиков связанных с железом событий, происходящих в системе. В качестве примера такого события можно привести промах мимо кешей процессора при обращении к оперативной памяти и, как следствие, вынужденное более дорогое обращение к оперативной памяти напрямую.

PMC устроены по-разному на разных CPU. Роль уровня абстракции над этими различиями во FreeBSD играет модуль ядра hwpmc.ko. Пользовательские приложения, такие, как pmccontrol и pmcstat, общаются с hwpmc.ko при помощи библиотеки libpmc. (В случае с Linux и perf, подозреваю, принцип аналогичный.)

От теории плавно переходим к практике.

Первым делом загружаем уже упомянутый hwpmc.ko:

sudo kldload hwpmc

Смотрим список доступных хардверных счетчиков:

sudo pmccontrol -l

Активируем все счечтики:

sudo pmccontrol -e *

Теперь мы можем посмотреть самый «горячие» процедуры конкретного процесса (аналог perf top) таким образом:

pmcstat -Pinstructions -T -t 19843

Пример вывода:

Топ самых горячих процедур в pmcstat

Не особо уступает perf, не так ли? Хотя постойте-ка, ведь perf позволяет нам «проваливаться» в процедуры и смотреть, какие именно строчки кода тормозят. Можно ли сделать то же самое при помощи pmcstat? Оказывается, что можно:

pmcstat -Pinstructions -t 20171 -O out.dat
pmcannotate out.dat / path / to / bin / postgres > annotate.txt
less -x8 annotate.txt

Пример вывода (по ширине обрезано мной):

CONVERSION STATISTICS:
#samples/total                           875683
Profile trace for function: strcmp() [10.18%]

Profile trace for function: _bt_compare() [7.59%]
0.90%| _bt_compare(Relation rel,
|             int keysz,
|             ScanKey scankey,
|             Page page,
|             OffsetNumber offnum)
| {
0.33%|   TupleDesc    itupdesc = RelationGetDescr(rel);
1.98%|   BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer…
4.70%|
|   /*
|    * Force result «>» if target item is first data item on a…
|    * — see NOTE above.
|    */
|   if (!P_ISLEAF(opaque) && offnum == P_FIRSTDATAKEY(opaque))
0.30%|     return 1;
8.19%|
|   itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, …
0.81%|    * We don’t test for violation of this condition here, how…
|    * initial setup for the index scan had better have gotten…
|    * _bt_first).
|    */
|
|   for (i = 1; i <= keysz; i++)
9.51%|   {
|     Datum           datum;
|     bool            isNull;
|     int32           result;

И снова ничем не уступает perf! Но постойте-ка, а как на счет построения флеймграфов? Никаких проблем, при помощи pmcstat их тоже можно строить:

pmcstat -Pinstructions -t 22456 -O pmc.out
pmcstat -R pmc.out -z16 -G pmc.graph
git clone https: // github.com / brendangregg / FlameGraph
perl . / FlameGraph / stackcollapse-pmc.pl pmc.graph > pmc.stack
perl . / FlameGraph / flamegraph.pl . / pmc.stack > pmc.svg

Ну и напоследок мне хотелось бы показать еще одну клевую штуку, которую умеет pmcstat — построение графа вызовов подобно тому, что мы ранее строили при помощи gprof:

sudo pkg install graphviz
sudo pip install gprof2dot
pmcstat -R pmc.out -g
gprof / path / to / bin / postgres INSTR_RETIRED_ANY / postgres.gmon > gprof.out
gprof2dot gprof.out | dot -Tsvg -o gprof.svg

Пример куска графа, полученного таким образом:

Граф вызовов, полученный с помощью pmcstat

Впрочем, на мой субъективный взгляд, флеймграфы куда проще для восприятия, чем графы вызовов, а показывают они при этом одно и то же.

Также pmcstat может считать уже упомянутые кэш-мисы, и, подозреваю, делать множество других умопомрачительных штук, про большинство из которых я пока даже не догадываюсь. Но, честно говоря, особой потребности в этих самых штуках у меня пока что нет, вот и поведать я о них не могу. Подробности заинтересовавшиеся читатели могут найти в man pmcstat , и далее по ссылкам.

А пользуетесь ли вы pmcstat, и если да, то как именно?

EnglishRussianUkrainian