Профилирование производительности в Linux с помощью gprof
Введение
Производительность — одна из ключевых проблем при разработке ПО. Профилирование помогает найти узкие места, мёртвый код и скрытые ошибки. В экосистеме GNU для этого существует утилита gprof, которая удобна для простого и быстрого получения данных о вызовах функций и времени их выполнения.
Важно: gprof работает на уровне функции (sampling + вызовы), поэтому он хорош для поиска «горячих» функций, но не всегда показывает проблемы на уровне системных вызовов или параллелизма.
Установка
В большинстве дистрибутивов gprof уже входит в пакет binutils. Если на вашей системе он отсутствует, установите пакет через менеджер пакетов.
Debian/Ubuntu:
sudo apt-get install binutilsRHEL/CentOS/Fedora:
sudo yum install binutilsПосле установки доступна команда gprof и генерация профайлинговых данных через компоновку с опцией -pg.
Требования и опции компилятора
Чтобы gprof собирал данные, исполняемый файл должен быть скомпилирован и слинкован с опцией -pg. Для gcc/clang это выглядит так:
gcc -Wall -pg test.c -o testЕсли вы разделяете этапы компиляции и линковки, добавьте -pg и туда, и туда. Для аннотированных листингов добавьте также -g (символы отладки).
Кратко:
- -pg — включить подсчёт профиля (обязательна при сборке и линковке)
- -g — сохранить отладочные символы (нужно для аннотации исходников)
Пример программы
Ниже — минимальный рабочий пример на C, который можно использовать для демонстрации работы gprof.
#include
void func2()
{
volatile int count = 0;
for (int i = 0; i < 1000000; ++i) {
count += i % 3;
}
}
void func1()
{
for (int i = 0; i < 10; ++i) {
func2();
}
}
int main()
{
func1();
printf("Done\n");
return 0;
} Этот код вызывает func2 многократно, поэтому profiler покажет func2 как «горячую» функцию.
Компиляция, запуск и генерация отчёта
- Скомпилируйте с -pg:
gcc -Wall -pg test.c -o test- Запустите программу как обычно:
./testПосле нормального завершения в текущей директории появится файл gmon.out. Он содержит сырые данные профилирования.
Сгенерируйте человеко-читаемый отчёт:
gprof test gmon.out > prof_output.txtФайл prof_output.txt будет содержать Flat profile и Call graph.
Important: gmon.out создаётся только при нормальном завершении процесса. Если программа завершилась через _exit() или была убита сигналом, файл может не появиться или быть неполным.
Разбор вывода gprof
Отчёт обычно разделён на две основные секции:
- Flat profile — список функций, сколько времени было потрачено непосредственно в каждой функции, число вызовов и среднее время на вызов.
- Call graph — дерево вызовов, показывающее, кто кого вызывает и как распределяется время между родителем и дочерними функциями.
Пример упрощённого фрагмента Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total name
time seconds seconds calls ms/call ms/call
100.00 1.00 1.00 10 0.100 0.100 func2
0.00 1.00 0.00 1 0.000 0.000 func1И пример упрощённого Call graph:
index %time self children called name
[1] 100.00 1.00 0.00 10/10 func2
[2] 0.00 0.00 1.00 1/1 func1Поля объясняются в начале prof_output; при желании подробные пояснения можно отключить ключом -b (brief):
gprof -b test gmon.out > prof_output.txtПолезные советы и ограничения
- Файл gmon.out создаётся в текущей рабочей директории; убедитесь, что есть права на запись.
- gprof использует семплирование времени и статический анализ вызовов, поэтому он может не точно отражать поведение многопоточных программ или коротких/быстрых функций.
- Для детального анализа исполнения на уровне строк используйте опции -g при компиляции и ключ -A у gprof:
gcc -Wall -pg -g test.c -o test
gprof -A test gmon.out > annotated.txt- Для визуализации call graph используйте внешний инструмент gprof2dot, который преобразует вывод в граф (dot) и даст возможность строить PNG/SVG.
Альтернативные инструменты
Если gprof не даёт нужной информации, рассмотрите альтернативы:
- perf (Linux perf) — низкоуровневое профилирование, хорош для системных вызовов и контекстов ядра.
- Valgrind/Callgrind + KCacheGrind — детальное профилирование и визуализация на уровне вызовов и строк.
- gperftools (Google Performance Tools) — встроенный CPU profiler с низкой нагрузкой.
- eBPF-инструменты (bcc, bpftrace) — для профайлинга в продакшн без модификации бинарников.
- py-spy / rbspy — для профайлинга интерпретируемых языков (Python/Ruby) без перезапуска.
Мини-методика профилирования (шаги)
- Изолируйте сценарий выполнения, который нужно профилировать (репрезентативный набор данных).
- Соберите бинарник с -pg (и -g при необходимости).
- Запустите программу до завершения, получите gmon.out.
- Сформируйте отчёт gprof и проанализируйте Flat profile и Call graph.
- При необходимости аннотируйте исходники (-A) и/или визуализируйте граф.
- Внесите изменения, повторите профилирование и сравните результаты.
Ролевые чек-листы
Для разработчика:
- собрать с -pg и -g
- прогнать репрезентативный сценарий
- сохранить prof_output и gmon.out для сравнения
Для QA/инжера по производительности:
- воспроизвести сценарий в контролируемой среде
- проверить влияние оптимизаций и изменений архитектуры
Для релизного инженера/админа:
- убедиться, что профилирование не включено в релизную сборку по умолчанию (избегать -pg в проде)
- при необходимости собирать отдельные демо-артефакты для анализа
Критерии приёмки
- Идентифицированы «горячие» функции, отвечающие за значительную часть времени выполнения.
- Внесённая оптимизация уменьшила время выполнения на проверенном сценарии или снизила нагрузку CPU/памяти.
- Результаты воспроизводимы и зафиксированы для регресс-тестов.
Глоссарий
- gprof — GNU profiler, инструмент для профилирования приложений на уровне функций.
- gmon.out — бинарный файл, создаваемый приложением при сборе профиля.
- Flat profile — табличный отчёт, показывающий время, проведённое в каждой функции.
- Call graph — граф вызовов функций с распределением времени между родителями и детьми.
Итог
gprof остаётся простым и удобным инструментом для быстрого получения представления о распределении времени между функциями в приложении. Для сложных сценариев и продакшн-анализа полезно комбинировать его с более современными инструментами (perf, eBPF, Valgrind). Всегда закрепляйте и документируйте профили перед изменениями, чтобы можно было объективно сравнить результаты.
Notes: если нужна инструкция по визуализации через gprof2dot или пример использования perf, я могу добавить шаги и примеры команд.
Похожие материалы
Шифрование USB‑накопителя с VeraCrypt
PowerShell: история команд — просмотр и сохранение
Nandroid — полная резервная копия Android
Ошибка 0x800f0806 в Windows 11 22H2
Извлечь ссылки с веб‑страницы PowerShell