Я пытаюсь создать профилировщик выборки, который работает в Linux, я не уверен, как отправить прерывание или как получить счетчик программы (pc), чтобы я мог узнать точку, в которой находится программа, когда я ее прерываю.
Я пытался использовать сигнал (SIGUSR1, Foo *) и вызывать обратную трассировку, но я получаю стек для потока, в котором я нахожусь, когда я поднимаю (SIGUSR1), а не для потока, в котором выполняется программа.
Я не совсем уверен, если это даже правильный способ сделать это …
Любой совет?
Вы можете отправить сигнал в конкретный поток, используя pthread_kill
и тид (gettid()
) целевого потока.
Правильный способ создания простых профилировщиков — использование setitimer
который может отправлять периодический сигнал (SIGALRM
или же SIGPROF
) например, каждые 10 мс; или posix таймеры (timer_create, timer_settime или timerfd), без необходимости отдельного потока для отправки сигналов профилирования. Проверьте источники google-perftools (gperftools), они используют setitimer или posix таймеры и собирают профиль с обратными следами.
Gprof также использует setitimer
для реализации профилирования времени процессора (9.1 Реализация профилирования — «В Linux 2.0… сделаны меры, чтобы ядро периодически доставляло сигнал процессу (обычно через setitimer ())»).
Например: результат поиска кода для setitimer
в источниках gperftools: https://code.google.com/p/gperftools/codesearch#search/&д = setitimer&кв = пакет: gperftools&тип = CS
void ProfileHandler::StartTimer() {
if (!allowed_) {
return;
}
struct itimerval timer;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 1000000 / frequency_;
timer.it_value = timer.it_interval;
setitimer(timer_type_, &timer, 0);
}
Вы должны знать, что у сетитимера есть проблемы с fork
а также clone
; он не работает с многопоточными приложениями. Есть попытка создать вспомогательную обертку: http://sam.zoy.org/writings/programming/gprof.html (неправильно) но я не Помните, это работает правильно (setitimer
обычно посылает сигнал всего процесса, а не весь поток). UPD: кажется, что начиная с ядра Linux 2.6.12, сигнал сетитимера направлен на весь процесс в целом (любой поток может получить его).
Чтобы направить сигнал от timer_create на конкретный поток, вам нужно gettid()
(#include <sys/syscall.h>
, syscall(__NR_gettid)
) а также SIGEV_THREAD_ID flag
. Не проверял, как создать периодический posix таймер с помощью thread_create (возможно, с timer_settime и ненулевое значение it_interval).
PS: в wikibooks есть обзор профилирования: http://en.wikibooks.org/wiki/Introduction_to_Software_Engineering/Tools/Profiling
если ты должен напишите профилировщик, позвольте мне предложить вам хороший (Увеличить) как ваша модель, не плохая (дргоЕ).
Это его характеристики.
Есть две фазы. Первый этап сбора данных:
Когда он берет образец, он читает весь стек вызовов, а не только счетчик программы.
Он может брать пробы, даже когда процесс заблокирован из-за ввода-вывода, сна или чего-либо еще.
Вы можете включать / выключать выборку, чтобы брать образцы только в те моменты, которые вас интересуют. Например, ожидая, пока пользователь что-то введет, выборка не имеет смысла.
Второй этап представления данных.
То, что у вас есть, представляет собой набор образцов стека, где образец стека представляет собой вектор адресов памяти, которые являются почти всеми адресами возврата.
Каждый обратный адрес указывает строку кода в функции, если только в какой-то системной подпрограмме у вас нет символической информации.
Ключевая часть полезной информации резидентская фракция (обычно выражается в процентах).
Если есть в общей сложности м образцы стека, и строка кода L присутствует в любом месте N из образцов, то его доля резидентности без маркировки.
Это верно, даже если L появляется больше, чем один раз на сэмпле, это все еще только один сэмпл, на котором он появляется.
Важность доли резидентства в том, что она прямо указывает, за какую долю времени отвечает оператор L.
Если вы взяли м = 1000 образцы, и L появляется на п = 300 из них доля резидентности L составляет 300/1000 или 30%.
Это означает, что если удалить L, общее время уменьшится на 30%.
Это обычно известно как включающий процент.
Вы можете определить долю резидентности не только для строк кода, но и для всего, что вы можете описать. Например, строка кода L находится внутри некоторой функции F.
Таким образом, вы можете определить долю резидентности для функций, в отличие от строк кода.
Это даст вам включительный процент по функциям.
Вы можете посмотреть на пары функций, например, на какую долю выборок вы видите функцию F, вызывающую функцию G.
Это даст вам информацию, которая составляет графы вызовов.
Есть все виды информации, которую вы можете получить из образцов стека.
Часто встречается «вид бабочки», где у вас есть «фокус» на одной строке L или функции F, а с одной стороны вы показываете все строки или функции, расположенные непосредственно над ней в выборках стека, а с другой сторона всех линий функций непосредственно под ним.
На каждом из них вы можете указать долю резидентов.
Вы можете нажать здесь, чтобы попытаться найти строки кода с высокой долей резидентности, которые вы можете найти способ устранить или уменьшить.
Вот как вы ускоряете код.
Что бы вы ни делали для вывода, я думаю, что очень важно позволить пользователю на самом деле исследовать небольшое количество из них, случайно выбранных.
Они передают гораздо больше информации, чем можно получить с помощью любого метода, который уплотняет информацию.
Как важно знать, что такое профилировщик должен делать, это также важно знать, что не сделать, даже если их делают многие другие профилировщики:
время сам. Бесполезный номер. Посмотрите на некоторые программы разумного размера, и вы поймете, почему.
количество вызовов Не поможет в поиске кода с высокой долей резидентности, и вы все равно не сможете получить его только с примерами.
высокочастотная выборка. Удивительно, сколько людей, конечно же, строителей профайлеров, думают, что важно получить много образцов. Предположим, линия L составляет 30% от 1000 образцов. Тогда его истинный инклюзивный процент составляет 30 +/- 1,4 процента. С другой стороны, если это на 30% 10 образцы, его включающий процент составляет 30 +/- 14 процентов. Это все еще довольно большой — достаточно большой, чтобы исправить. В большинстве профилировщиков люди думают, что им нужна «числовая точность», поэтому они берут много выборок и накапливают то, что они называют «статистикой», а затем выбрасывают выборки. Это все равно что выкапывать алмазы, взвешивать их и выбрасывать. Реальная ценность в самих образцах, потому что они говорят вам, в чем проблема.