Эта утилита предназначена для статистического (сэмплирующего) профилирования приложений, работающих под Mono в Linux-x86_64.
Особенность этого способа профилирования заключается в том, что в результате получается диаграмма распределения полного времени ("wall time") на выполнение отдельных методов. В полное время входит on-CPU-время (т.е., время на непосредственное выполнение кода), так и off-CPU-время (время, потраченное на ожидание ввода-вывода или на синхронизацию).
Предварительно следует установить пакеты с отладочной информацией для используемых библиотек. В частости, под CentOS/Fedora следует установить
пакет mono-core-debuginfo
.
Следует отдельно запустить профилируемый процесс. Очень важно, чтобы при запуске процесса были учтены:
- должна быть указана переменная окружения
MONO_DEBUG=disable_omit_fp
- к команде запуска mono должен быть добавлен аргумент
--jitmap
.
Пример запуска ASP.NET-приложения из командной строки для профилирования:
$ cd /path/to/web-app
$ MONO_DEBUG=disable_omit_fp /usr/bin/mono --jitmap /usr/lib/mono/4.5/xsp4.exe --nonstop --port=5000
Профилировщик можно запускать из командной строки:
$ ./mono_ssp --pid "$(pgrep -f 'mono.*xsp4.exe')" --perf_script --duration_sec 120 --interval_ms 1 > prof.txt
Следует указать следующие параметры запуска:
--pid PID
. Идентификатор профилируемого процесса--perf_script
и> prof.txt
. Опция--perf_script
означает, что на стандартный вывод будут выводиться сэмплы в формате, совпадающем с форматом вывода утилитыperf script
.> prof.txt
- это перенеправление стандартного вывода в файл.--duration_sec SECONDS
. Указывается длительность профилирования в секундах (можно указывать только целое количество секунд)--interval_ms MILLISECONDS
. Периодичность снятия сэмплов (в миллисекундах). (Замечание: т.к. сейчас скорость снятия сэмплов маленькая, то указанная периодичность не гарантируется).
При успешном выполнении будет выведено сообщение:
Profile completed. Took 133 process samples in 120.227 seconds
и сформирован файл prof.txt
(файл содержит сырые (необработанные) результаты профилирования).
Для анализа результатов профилирования рекомендуется использовать один из 2 инструментов - FlameGraph и speedscope.
FlameGraph - это обзорная визуализация распределения времени по стэктрейсам. см. http://www.brendangregg.com/flamegraphs.html для более подробного описания.
Для построения flamegraph'а следует:
-
Склонировать репозиторий https://github.com/brendangregg/FlameGraph
-
Запустить утилиту flamegraph:
$ /path/to/FlameGraph/stackcollapse-perf.pl < prof.txt | /path/to/FlameGraph/flamegraph.pl > prof.flamegraph.svg
(где
prof.txt
- это файл с сырыми результатами профилирования)
speedscope - это инструмент для интерактивного анализа результатов трассировки и профилирования.
Его можно открывать в браузере по адресу https://www.speedscope.app/ (файлы с результатами профилирования не передаются в интернет и полностью анализируются в браузере) или установить локально через NPM.
Описание вариантов запуска и установки: https://github.com/jlfwong/speedscope#usage
Так как speedscope умеет открыть файлы в формате perf script
, то достаточно открыть speedscope и импортировать файл с результатами профилирования
(prof.txt
).
Утилита mono-ssp основана на периодическом сборе (сэмплировании) стэков вызовов всех нитей (потоков) процесса. В отличие от CPU-профилировщиков
(например, perf record
(кроме отдельных специфических режимов)), в этом результате учитывается время ожидания (ожидания ответа от БД, ожидание чтения данных с диска или по сети) и синхронизации (блокировки, ожидание окончания сборки мусора, бесконечное ожидание, ожидание задач из очереди задач). Для того, чтобы
точнее сказать, в чем причина долгой операции (большое потребление CPU или большое ожидание) - следует произвести также CPU-профилирование и сравнить их результаты.
В результате профилирования будет много стэктрейсов, оканчивающихся на pthread_cond_timedwait
, nanosleep
и т.п. Их обычно можно игнорировать.
FlameGraph схлопывает стэки всех нитей (потоков), поэтому в нем большие одинаковые участки графика можно игнорировать - они соответствуют нитям, которые ожидают работы и не потребляют ресурсов.
Если цепочка вызовов в стэктрейсе оканчивается на sigsuspend
- то это, вероятно, ожидание завершения сборки мусора в Mono.
Для сборки необходимо наличие:
- g++
- meson
- ninja
- libunwind и libunwind-dev
Шаги сборки:
-
Скачать исходники mono-ssp
-
Создать где-нибудь временный каталог и перейти в этот каталог
-
В созданном каталоге выполнить команды:
$ meson /path/to/mono-ssp --buildtype release $ ninja
-
В результате получится исполняемый файл meson_ssp (и набор промежуточных файлов).