Какие методы вы можете использовать для профилирования вашего кода

StackOverflow https://stackoverflow.com/questions/285710

Вопрос

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

Целевым языком является C ++.

Мне интересно, что вы лично использовали.

Это было полезно?

Решение

Я нашел следующее весьма полезным:

#ifdef PROFILING
# define PROFILE_CALL(x) do{ \
    const DWORD t1 = timeGetTime(); \
    x; \
    const DWORD t2 = timeGetTime(); \
    std::cout << "Call to '" << #x << "' took " << (t2 - t1) << " ms.\n"; \
  }while(false)
#else
# define PROFILE_CALL(x) x
#endif

Что можно использовать в вызывающей функции как таковой:

PROFILE_CALL(renderSlow(world));
int r = 0;
PROFILE_CALL(r = readPacketSize());

Другие советы

Без шуток: в дополнение к выводу времени в std :: cout и другим подходам, ориентированным на текст / данные, я также использую функцию Beep (). Есть что-то о том, чтобы услышать разрыв тишины между двумя "Beep" контрольно-пропускные пункты, которые производят другое впечатление.

Это похоже на разницу между просмотром нот и написанием музыки. Это как разница между чтением rgb (255,0,0) и красным огнем.

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

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

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

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

Если это что-то достаточно длинное (например, минута или более), я запускаю программное обеспечение в отладчике, затем несколько раз прерываю работу и вижу, где происходит сбой отладчика, это дает очень приблизительное представление о том, что работает программное обеспечение. к (например, если вы сломаете 10 раз, и они все в одном месте, это говорит вам кое-что интересное!). Очень грубый и готовый, но не требует никаких инструментов, инструментов и т. Д.

Я не уверен, какие платформы вы имели в виду, но на встроенных микроконтроллерах иногда полезно прокрутить запасную линию цифрового выхода и измерить ширину импульса с помощью осциллографа, счетчика / таймера или логического анализатора.

Я бы использовал правило 80/20 и поместил таймеры вокруг горячих точек или интересных путей вызова. Вы должны иметь общее представление о том, где будут находиться узкие места (или, по крайней мере, большинство путей выполнения), и использовать соответствующий зависящий от платформы таймер высокого разрешения (QueryPerformanceCounters, gettimeofday и т. Д.).

Я обычно ничего не беспокою при запуске или завершении работы (если это не требуется), и у меня есть четко определенные «точки дросселирования», обычно передача сообщений или какой-то алгоритмический расчет. Я обычно обнаружил, что приемники сообщений / srcs (приемники более), очереди, мьютексы и просто простые сообщения (алгоритмы, циклы) обычно составляют большую часть задержки в пути выполнения.

Вы используете Visual Studio?

Вы можете использовать переключатели / Gh и / GH. Вот пример проверки стека

Эти флаги позволяют вам по отдельности регистрировать недекорированные функции, которые вызываются каждый раз, когда метод вводится и / или остается во время выполнения.

Затем вы можете зарегистрировать все данные профилирования, а не только информацию о времени. Стеки-дампы, адрес вызова, адрес возврата и т. Д. Что важно, потому что вы, возможно, захотите знать, что «функция X использовала время Y под функцией Z», а не только общее время, проведенное в функции X.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top