Как стать автором
Обновить

Комментарии 13

В чем проблема с инлайн-функциями? Если компилятор заменяет вызов некоторой функции на ее код, значит можно считать, что данной функции вообще нет. А если нет функции, зачем ее профайлить?
Тут есть несколько проблем
1) Сложнее понять стек вызовов, когда половина функций заинлайнилась, а половина нет.
2) Сложно оценить относительное время работы функций
Всетаки если бы программист хотел, чтобы «функции вообще нет», то он наверно и не писал бы функцию. А если функция есть, значит каким-то целям программиста она служила.
Не хотите неявных инлайнов — не просите об этом компилятор.
Вы же зачем-то собираетесь с опцией -Ofast — а это означает то же самое, что -O3, плюс ещё «optimizations that are not valid for all standard-compliant programs» (звучит довольно пугающе, если честно).
-O3 в свою очередь разрешает компилятору самостоятельно принимать ряд решений касательно инлайна.
При любом уровне оптимизаций будут инлайны.
Сейчас попробовал перезапустить один из примеров, и на уровнях оптимизации Ofast, O3, O2 инлайн все также был. Его не было только при явном указании fno-inline и при опции Og.

А с Ofast так случайно получилось. Когда я подготовил большую часть примеров, то с удивлением обнаружил, что все они скомпилированы с этой опцией, хотя планировал собирать с O3
Вообще инлайны — конечно, будут при любом уровне оптимизации. Если Вы их попросите в коде — явно (с помощью ключевого слова inline) или неявно (размещая определение member-function прямо в объявлении класса).

А вот с инлайнами по инициативе компилятора ситуация несколько иная.
Для -O0 — компилятор не будет вмешиваться
Для -O1 будет -finline-functions-called-once
Для -O2 будет -finline-functions-called-once + -finline-small-functions
Для -O3 будет -finline-functions-called-once + -finline-small-functions + -finline-functions

Фраза «при любом уровне оптимизаций будут инлайны» не совсем корректна — -O0 это тоже как бы уровень. Ну и вручную нарулить отдельных опций тоже никто не запрещает.

Проблема возникает тогда, когда заинлайненый код тормозит, а а стеке показывается, что тормозит другая функция. И ты ломаешь голову, какой же именно код тормозит)

функция может и «не существует», а вот её код выполняется и, иногда, тормозит

Приходилось только несколько лет назад профилировать win32/64 приложения под VS. Вроде результаты добывались несложно и были адекватными.

Ломаю голову, пытаясь профилировать read-write блокировки (pthread_rwlock). Очень хочется узнать время ожидания на каждой блокировке, т.е. найти самую дорогую. Есть варианты?

Ну есть профайлеры, которые показывают загрузку потокв в динамике. Но думаю это не сильно поможет для данной задачи.
Я бы сделал обертку для lock-а и собирал бы время там, если не найдется решения получше
Мне кажется тут может помочь Off-CPU анализ. Можно попробовать подписаться на евенты планировщика с помощью perf и отслеживать когда треды уходят в ожидание:

echo 1  | sudo tee /proc/sys/kernel/sched_schedstats # надо разрешить сбор статов планировщика

sudo perf record -e sched:sched_stat_sleep -e sched:sched_switch -e sched:sched_process_exit -g --call-graph=dwarf -- ./a.out # a.out -- ваш бинарь, скомпиленный с дебаг символами (иначе стека не увидим)

# Ждём пока программа завершиться и perf выплюнет perf.data файл
sudo perf report # запускается tui'шка в которой можно посмотреть где эти евенты происходили


Легче конечно получить FlameGraph и по нему глянуть. Как это сделать можно глянуть тут. Или с помощью bcc/tools/offcputime.
Спасибо, попробую.
Было бы здорово код, скрипты сборки и результаты статьи выкладывать на github для удобства читателям.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации