- PVSM.RU - https://www.pvsm.ru -

Профилирование приложений в Qt Creator с помощью gprof

Требования к производительности ПО разные: для каких-то приложений она критична, для каких-то — нет. И даже если нет жестких ограничений, нам всегда хочется, чтобы наше ПО работало быстрее. Одним из методов, позволяющих выявить «узкие» места приложения для дальнейшей оптимизации, является профилирование.

На моей текущей работе в качестве основной IDE используется Qt Creator. Когда возникла необходимость использовать профилировщик в одном из проектов, я решил опробовать gprof, входящий в состав MinGW и поэтому не требующий никаких дополнительных действий по установке.

Профилирование с помощью gprof состоит из нескольких шагов:

  • компилирование и сборка программы с включенной опцией профилирования,
  • исполнение программы для создания файла данных о профиле,
  • запуск gprof для анализа полученного файла данных о профиле.

Результатом анализа являются две таблицы — «простой профиль» (flat profile) и «граф вызовов» (call graph).

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

В графе вызовов отображается информация о каждой функции: какие функции её вызывали, какие функции и сколько раз вызывала она, а также сколько времени было затрачено на выполнение подпрограмм. Это может указать на места, в которых вы можете попытаться исключить вызовы функций, требующих много процессорного времени.

А теперь обо всем поподробнее

Чтобы скомпилировать программу для профилирования, в файл проекта Qt необходимо добавить строки:
QMAKE_CXXFLAGS_DEBUG += -pg
QMAKE_LFLAGS_DEBUG += -pg

Если использование профилировщика больше не планируется, не забываем убирать эти опции: в противном случае исполнение будет проходить несколько медленнее обычного, т.к. требуется время на сбор и запись данных о профиле.

После добавления необходимых опций в файл проекта необходимо собрать и запустить отладочную версию программы, выполнить тот функционал программы, информацию о котором вы хотите получить, и завершить работу. После завершения программы в текущей директории будет создан файл gmon.out. Отмечу, что в случае аварийного завершения работы выходной файл создан не будет.

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

Полученный файл gmon.out как раз и анализируется профилировщиком gprof.

Для удобства использования настроим вызов gprof прямо из IDE:
1. Переходим на нужную панель:
Инструменты->Параметры->Среда->Внешние утилиты
2. Выбираем раздел, куда следует добавить профилировщик.
3. Настраиваем gprof:
Описание: любое понятное вам описание
Программа: полный путь к утилите gprof
Параметры: %{CurrentProject:Path}/debug/*.exe > file_name.txt
Рабочий каталог: %{CurrentProject:Path}

Должно получится что-то вроде этого:
image

В поле параметры при необходимости добавьте те опции, которые вам удобны. Я, например, добавляю '--brief' для вывода только самого необходимого, иначе помимо двух таблиц на выдачу пойдет еще много-много разных букв.

Пункт меню вызова профилировщика ищите в разделе меню «Инструменты», подпункте «Внешние».
После запуска gprof будет создан текстовый файл file_name.txt, куда мы перенаправили вывод анализа, и который мы сами можем внимательно изучить.

gprof в действии

Приведем пример приложения, выполняющегося достаточно продолжительное время:

void functionA()
{
    int sum = 0;
    while (sum < 10e5)
        sum++;
}

void functionB()
{
    int sum = 0;
    while (sum < 30e5)
        sum++;
}

int main()
{
    int iterations = 1500;

    while (iterations--) {
        functionB();
        functionA();
    }
	
    return 0;
}

Приложение содержит функции functionA и functionB, в которых выполняются длительные циклы. Функция main просто поочередно вызывает обе этих функции заданное количество раз, а именно 1500. В функции functionB цикл выполняется в три раза дольше, поэтому ожидаемый процент затраченного на нее процессорного времени составляет 75%. Давайте проверим наши ожидания, получив и проанализировав профилировщиком файл gmon.out:

Flat profile:
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ms/call  ms/call  name    
 75.08      7.35     7.35     1500     4.90     4.90  functionB()
 24.92      9.79     2.44     1500     1.63     1.63  functionA()

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

Более подробную информацию можно увидеть в графе вызовов:

Call graph (explanation follows)	 
granularity: each sample hit covers 4 byte(s) for 0.10% of 9.79 seconds

index % time    self  children    called     name
                                                 <spontaneous>
[1]    100.0    0.00    9.79                 main [1]
                7.35    0.00    1500/1500        functionB() [2]
                2.44    0.00    1500/1500        functionA() [3]
-----------------------------------------------
                7.35    0.00    1500/1500        main [1]
[2]     75.1    7.35    0.00    1500         functionB() [2]
-----------------------------------------------
                2.44    0.00    1500/1500        main [1]
[3]     24.9    2.44    0.00    1500         functionA() [3]
-----------------------------------------------

Итак, основными плюсами gprof для профилирования приложений в Qt Creator являются отсутствие каких-либо дополнительных действий по установке, ведь мы уже имеем установленный MinGW, а также простота настройки и использования.

При написании статьи использовались:
— Qt Creator версии 2.4.1,
— профилировщик gprof версии 2.19.1
— материалы сайта www.cs.utah.edu/dept/old/texinfo/as/gprof.html [1]

Автор: eazzy


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/qt-2/10777

Ссылки в тексте:

[1] www.cs.utah.edu/dept/old/texinfo/as/gprof.html: http://www.cs.utah.edu/dept/old/texinfo/as/gprof.html