Как сделать профилирование настенных часов с помощью dtrace? Или как подсчитать неиспользуемые образцы с поставщиком профиля?

Я разрабатываю плагин для стороннего хост-приложения на OSX, используя C ++. Он скомпилирован как .dylib. Я хочу профилировать мой плагин, поскольку он работает в хост-приложении.

К сожалению, хост вызывает код плагина со скоростью, которая варьируется в зависимости от (последнего) времени исполнения плагина. Это означает, что общее время процесса может значительно отличаться от реального времени. Поэтому с профилировщиком выборки «время, потраченное» внутри плагина, на самом деле не основывается на чем-либо полезном, поскольку оно сравнивается только с кадрами стека, которые попадают в процесс. Если я улучшу производительность плагина, то схема исполнения плагина на хосте изменится соответствующим образом, и будет очень сложно измерить улучшения внутри плагина.

Я могу использовать инструменты, но, насколько я могу судить, я могу получить только относительное время по сравнению с временем процессора.

Я использовал dtrace для получения пользовательской гистограммы стека хост-процесса:

#!/usr/sbin/dtrace -s

#pragma ustackframes 100
#pragma D option quiet

/* $1 is pid  */
/* $2 is sample rate in Hz (e.g. 100)  */
/* $3 is duration (e.g. '20s')  */

profile-$2
/pid == $1 && arg1/
{
@[ustack()] = count();
}

tick-$3
{
exit(0);
}

Это работает, но все же предоставляет только выборки относительно времени процесса, поскольку предикат сопоставляется только тогда, когда процесс находится в пространстве пользователя. Даже удаляя && arg1 условие для его запуска во время вызовов ядра процесса не очень помогает.

То, что я действительно хочу знать, это сколько profile-n образцы привели к тому, что процесс вообще не запущен. Затем я могу сравнить число в моем плагине с общим количеством образцов и получить абсолютный примеры значений для функций моего плагина. Это заставляет меня задуматься — можно ли предположить, что запрошенный profile-n Частота дискретизации Могу ли я просто взять частоту дискретизации time * и использовать ее для вычисления времени «вне процесса»? Я предполагал, что, скажем, на 1500 Гц, он сбрасывал сэмплы и работал с некоторой другой, неизвестной частотой, но если я могу быть уверен, что это сэмплирование на 1500 Гц, тогда я могу рассчитать время «вне процесса» из этого.

Альтернативно, есть ли известный способ сделать настенные часы профилирование с помощью dtrace?

1

Решение

Это заставляет меня задуматься — можно ли предположить, что запрошенный profile-n Частота дискретизации

В Solaris это не гарантируется: некоторым старым аппаратным средствам не хватает необходимой поддержки для прерываний на основе таймера произвольного разрешения. Я бы предположил, что такое же теоретическое ограничение относится к DTrace OS X.

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

bash-3.2# cat test.d
uint64_t last;

profile-1500
/cpu == 0/
{
now = timestamp;
@ = lquantize(now - last, 500000, 800000, 30000);
last = now;
}

tick-1
/i++ == 10/
{
exit(0);
}
bash-3.2# dtrace -qs test.dvalue  ------------- Distribution ------------- count
560000 |                                         0
590000 |@@@                                      1041
620000 |@@@@@@@@@@                               4288
650000 |@@@@@@@@@@@@@@                           5680
680000 |@@@@@@@@@@                               3999
710000 |@@@@                                     1451
740000 |                                         0
770000 |                                         0
>= 800000 |                                         1

bash-3.2#

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

После обсуждения в комментариях, вот как вы можете измерить затраченное время внутри данной функции:

pid$target:mylib:myfunc:entry
/!self->depth/
{
self->depth = ustackdepth;      /* beware recursion */
self->start_time = timestamp;   /* for relative wall time calculations */
self->start_vtime = vtimestamp; /* CPU time */
}

pid$target:mylib:myfunc:return
/ustackdepth == self->depth/
{
printf("%d ms (real) %d ms (CPU)\n",
(timestamp - self->start_time) / 1000000,
(vtimestamp - self->start_vtime) / 1000000);
self->depth = 0;
}

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

Вполне возможно выполнить аналогичное упражнение для всех функций в вашей библиотеке, хотя это может быть довольно обременительной задачей — исключить ложные результаты из рекурсии и оптимизации хвостовых вызовов. Чтобы быть более полезным, вы, вероятно, также захотите исключить из стоимости функции время, потраченное на вызов стека; это делает работу еще тяжелее (но не невозможной). Таким образом, вооружившись вышеуказанными средствами для создания объективного ориентира, я был бы более склонен упорствовать с подходом профилирования, возможно, что-то вроде

# cat sample.d
profile-997
/pid == $target && arg1 >= $1 && arg1 < $2/
{
@[ufunc(arg1)] = count();
}

END
{
trunc(@,5);
exit(0);
}
#

Это захватывает пять наиболее часто встречающихся функций в данной области памяти. Например (и используя pmap на солярисе найти libc),

# dtrace -qs sample.d -p `pgrep -n firefox` 0xfc090000 0xfc200000
^C

libc.so.1`mutex_lock_impl                                        35
libc.so.1`clear_lockbyte                                         46
libc.so.1`gettimeofday                                           71
libc.so.1`memset                                                 73
libc.so.1`memcpy                                                170
#

Это оказывается довольно хорошей иллюстрацией преимущества выборки: memcpy() а также memset() закодированы вручную в сборке — то есть мы обнаруживаем, что наиболее трудоемкие функции уже оптимизированы.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector