Руководство по Gprof: профилирование C/Fortran на Linux
Gprof — классический инструмент для профилирования программ на C, Pascal и Fortran77 в Unix-подобных системах. В статье показано, как установить Gprof, скомпилировать программу с опцией -pg, собрать gmon.out и прочитать вывод (flat profile и call graph). Также разбор ограничений инструмента и альтернативы для более сложных задач.
Для кого это руководство
Для разработчиков, которые пишут на C/Fortran и используют Linux как платформу разработки. Подойдёт как быстрый вводный материал и чеклист для первичного анализа «горячих точек» в коде.
Что такое Gprof?
Gprof — это инструмент профилирования, который собирает статистику выполнения: сколько времени и сколько вызовов приходятся на каждую функцию. Он использует генерацию служебного кода при компиляции (опция -pg у gcc), создаёт файл gmon.out и затем анализирует его, выводя две основные секции:
- Плоский профиль (flat profile): сколько времени заняла каждая функция и сколько раз она была вызвана. Это помогает быстро увидеть «пожирателей циклов».
- Граф вызовов (call graph): кто кого вызывал, сколько раз, и какова оценка времени, потраченного в дочерних функциях. Это полезно, чтобы понять вклад вложенных вызовов.
Краткое определение: профилирование — измерение времени и частоты вызовов функций, чтобы найти узкие места производительности.
Системные требования и примечания
- Примеры тестировались на Ubuntu 14.04 LTS с gprof 2.24. На других дистрибутивах поведение может незначительно отличаться.
- Gprof подходит для одно-процессных и несложных многопоточных программ, но имеет ограничения (ниже).
Важно: чтобы gprof собирал данные, исходники и линковка должны выполняться с опцией -pg.
Установка Gprof
Проверьте, установлен ли gprof командой:
$ gprofЕсли вы увидите сообщение вида:
$ a.out: No such file or directory— это означает, что сам бинарный инструмент доступен в системе. Если gprof не найден, установите пакет binutils:
$ apt-get install binutilsПример использования: шаг за шагом
Ниже — минимальный пример на C, специально написанный для иллюстрации работы gprof.
//test_gprof.c
#include
void func4(void)
{
printf("\n Inside func4() \n");
for(int count=0;count<=0XFFFF;count++);
}
void func3(void)
{
printf("\n Inside func3() \n");
for(int count=0;count<=0XFFFFFFF;count++);
}
void func2(void)
{
printf("\n Inside func2() \n");
for(int count=0;count<=0XFFF;count++);
func3();
}
void func1(void)
{
printf("\n Inside func1() \n");
for(int count=0;count<=0XFFFFFF;count++);
func2();
}
int main(void)
{
printf("\n main() starts...\n");
for(int count=0;count<=0XFFFFF;count++);
func1();
func4();
printf("\n main() ends...\n");
return 0;
} Скомпилируйте программу с опцией -pg (эта опция добавляет код, записывающий статистику выполнения):
$ gcc -Wall -std=c99 -pg test_gprof.c -o test_gprofЗапустите бинарник:
$ ./test_gprofПосле выполнения в текущей директории появится файл gmon.out — это сокровищница данных профилирования.
Сгенерируйте удобочитаемый отчёт:
$ gprof test_gprof gmon.out > profile-data.txtОбщий синтаксис: gprof [имяисполняемогофайла] gmon.out > [файл_отчёта]
Разбор вывода: flat profile
Ниже — пример секции flat profile, которую выводит gprof:
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ms/call ms/call name
96.43 0.81 0.81 1 810.00 810.00 func3
3.57 0.84 0.03 1 30.00 840.00 func1
0.00 0.84 0.00 1 0.00 810.00 func2
0.00 0.84 0.00 1 0.00 0.00 func4Пояснения к полям (перевод и интерпретация):
- % time — процент времени процесса, потраченный непосредственно в этой функции (self).
- cumulative seconds — накопленное суммарное время до текущей строки.
- self seconds — время, потраченное непосредственно в теле функции (без учёта дочерних вызовов).
- calls — количество вызовов функции.
- ms/call (self) — миллисекунд времени на один вызов самой функции.
- ms/call (total) — миллисекунд времени на вызов вместе с временем дочерних функций.

Разбор вывода: call graph
Секция call graph показывает, кто кого вызывал и какова оценка времени в дочерних функциях. Пример из вывода ниже:
Call graph (explanation follows)
granularity: each sample hit covers 4 byte(s) for 1.19% of 0.84 seconds
index % time self children called name
0.03 0.81 1/1 main [2]
[1] 100.0 0.03 0.81 1 func1 [1]
0.00 0.81 1/1 func2 [3]
-----------------------------------------------
[2] 100.0 0.00 0.84 main [2]
0.03 0.81 1/1 func1 [1]
0.00 0.00 1/1 func4 [5]
-----------------------------------------------
0.00 0.81 1/1 func1 [1]
[3] 96.4 0.00 0.81 1 func2 [3]
0.81 0.00 1/1 func3 [4]
-----------------------------------------------
0.81 0.00 1/1 func2 [3]
[4] 96.4 0.81 0.00 1 func3 [4]
-----------------------------------------------
0.00 0.00 1/1 main [2]
[5] 0.0 0.00 0.00 1 func4 [5] Ниже — несколько скриншотов, поясняющих элементы call graph в выводе gprof:



Важно: если вы хотите скрыть пояснения и подсказки в выходном файле, используйте опцию -b у gprof.
Частые ошибки и когда Gprof не подойдёт
- Многопоточность: gprof плохо работает с приложениями, активно использующими pthreads; сбор данных может быть неполным или некорректным.
- Встроенные (inlined) функции и оптимизации компилятора: агрессивная оптимизация (O2/O3) и inlining изменяют представление функций в профиле.
- Системные вызовы и внешние библиотеки: время, потраченное внутри ядра или в библиотеке, не всегда корректно приписывается вашим функциям.
- Краткие/очень быстрые функции: если функция выполняется быстрее разрешения выборки, она может не попасть в статистику.
Если ваша программа многопроцессная, интенсивно использует I/O или требует трассировки системных вызовов, рассмотрите альтернативы ниже.
Альтернативы Gprof (когда нужна другая модель)
- perf (Linux perf tools): инструмент на более низком уровне, подходит для системных профилей, трассировки и анализа многопоточных приложений.
- Valgrind + Callgrind / KCachegrind: детальное профилирование вызовов на основе эмуляции — медленнее, но точнее по количеству инструкций/переходов.
- gperftools (Google Performance Tools): предоставляет heap/CPU профилирование с минимальным влиянием на производительность.
- oprofile: системный профайлер, работает с ядром и пользовательским пространством.
Выбор зависит от задачи: gprof быстрый и простой для ознакомительного профилирования; perf/valgrind даёт больше точности и возможностей.
Быстрая методика профилирования (минимальная рабочая процедура)
- Соберите сборку с символами отладки (опция -g) и добавьте -pg при компиляции и линковке.
- Прогоняйте реалистичные сценарии нагрузки, чтобы gmon.out содержал репрезентативные данные.
- Сгенерируйте отчёт gprof и откройте flat profile для поиска «горячих» функций.
- Изучите call graph, чтобы понять, откуда приходят самые затратные вызовы.
- Примените оптимизацию в коде (изменение алгоритма, уменьшение вызовов и пр.) и повторите измерение.
- Сравните profile-data.txt до и после изменений.
Минимальная проверка перед релизом: убедиться, что профилирование прогонов с тестовыми данными даёт стабильные результаты и что оптимизации не изменили семантику.
Рекомендации по использованию опции -pg
- Добавляйте -pg для всех исходных модулей, которые должны участвовать в профилировании; если собрать частично, отчёт будет неполным.
- При линковке также используйте -pg, иначе runtime-инфраструктура профилирования не будет подключена.
- Для сборки релизов не оставляйте -pg: он добавляет накладные расходы.
Критерии приёмки
- Профилирование выполнялось на репрезентативных данных/наборе тестов.
- Flat profile показывает явные кандидаты для оптимизации (функции с существенным self time).
- После оптимизаций общее время выполнения снизилось, а функциональность не изменилась.
- Регрессий в многопоточности/памяти не появилось.
Чек-листы по ролям
Разработчик:
- Собрать с -pg и -g.
- Прогнать сценарии и сохранить gmon.out.
- Сгенерировать profile-data.txt и отметить кандидатов для оптимизации.
Код-ревьювер / тим-лид:
- Проверить, что изменение улучшает метрики (латентность/время выполнения).
- Убедиться, что оптимизация не ухудшает читаемость и тесты проходят.
Факто-бокс
- Формат отчёта делится на flat profile и call graph.
- gmon.out — бинарный файл с данными профилирования, генерируется при запуске программы, скомпилированной с -pg.
- Опция gcc -pg обязательна и при компиляции, и при линковке.
- Для небольших тестов вывод gprof указывает: “Each sample counts as 0.01 seconds” — это сообщение отражает разрешение выборки в конкретном запуске.
Ментальные модели при профилировании
- «80/20»: часто 20% кода съедают 80% времени — сначала ищите эти «горячие точки» по flat profile.
- «Верх вниз»: начните с внешних вызовов (main), затем спускайтесь по call graph, чтобы понять контекст затрат.
- «Измеряй, меняй, проверяй»: одна оптимизация за раз, с измерением до и после.
Примеры паттернов оптимизации
- Уменьшение количества вызовов тяжёлой функции (кэширование результатов).
- Перенос горячего кода в более оптимальную реализацию (векторизация, алгоритмы с меньшей сложностью).
- Снижение аллокаций в горячих путях.
Глоссарий (одна строка на термин)
- Профилирование — измерение времени и частоты выполнения частей программы.
- Sampling — метод профилирования, где периодически снимаются снимки состояния стека.
- Instrumentation — вставка кода для подсчёта вызовов/времени.
- Flat profile — таблица, показывающая время, потраченное непосредственно в функциях.
- Call graph — граф вызовов, показывающий взаимосвязи между функциями.
Когда переходить на другие инструменты
- Нужна профилировка ядра/системных вызовов — используйте perf или oprofile.
- Нужна высокая точность и анализ инструкций — valgrind/callgrind.
- Нужно минимальное влияние на производительность при сборе данных в проде — рассмотрите gperftools.
Резюме
Gprof — удобный и простой инструмент для начального профилирования приложений на C/Fortran в Linux. Он даёт быстрый flat profile и call graph, достаточные для нахождения очевидных узких мест. Для продвинутого анализа и многопоточных приложений лучше использовать perf или valgrind.
Если вы уже используете Gprof и хотите поделиться приёмами или примерами, оставьте комментарий — практические сценарии и обмен опытом ценны для сообщества.
Заключение
Мы затронули основы: установка, компиляция с -pg, запуск, генерация profile-data.txt и разбор flat profile и call graph. Это отправная точка — дальше можно изучать опции gprof и переходить к более мощным инструментам при необходимости.
Похожие материалы
Несколько аккаунтов Skype: Multi Skype Launcher
Журнал для работы: повысить продуктивность
Персональные звуки уведомлений на Android
Скачивание шоу Hulu для офлайн‑просмотра
Microsoft Start: персонализированная новостная лента