Sponsored LinksКатегорииLinksUnix Tutorial
Personal Development Ruslan Valiev Solaris Performance Team Damien Farnham Fintan Ryan Nicky Veitch Niall Mullen Sean McGrath DTrace Bryan Cantrill Brendan Gregg ZFS Tim Foster General Ben Rockwood Learning Solaris 10 Privacy policy |
Wednesday, 12 January. 2005DTrace: агрегирующие функции (агрегации)
Очень часто при наблюдении за производительностью системы важно знать не каждый конкретный случай, когда выполняется та или иная проба DTrace, а видеть общую картину . Например, наблюдая за каким-то процессом, поедающим процессорное время согласно prstat, мы задаём себе вопрос: а чем же занимается этот процесс? И часто под этим вопросом мы имеем в виду не конкретно каждый системный вызов, выполняемый процессом, а количество этих вызовов.
Агрегации DTrace как раз и созданы для ответов на подобные вопросы. Оперируя c числовыми наборами данных, агрегирующие функции помогают нам легко определять средние, максимальные и минимальные величины, подсчитывать количество и сумму элементов набора и распределения частот элементов. Подробнее об агрегирующих функциях можно прочесть здесь, а сегодня я лишь приведу один из примеров. DTrace хранит результаты выполнения агрегирующих функций в объектах, которые и называются агрегациями. Синтаксис определения агрегации таков: @name[ keys ] = aggfunc ( args ); здесь: name - название нашей агрегации keys - ключи-индексы агрегации, очень похожи на знакомые многим ключи ассоциативных массивом aggfunc - агрегирующая функция args - аргументы функции, обычно это числовой ряд В сегодняшнем примере я использую агрегирующую функцию sum, которая, как видно из названия, вычисляет сумму элементов указанного числового ряда. В памяти хранится лишь текущее значение агрегирующей функции, вычисленное на основе предыдущих значений аргументов, к которому применяется эта же функция для текущего значения аргумента. Для поверхностного анализа можно использовать меньше ключей для нашей агрегации - например, только pid, без указания thread'ов, или даже execname - но в этом случае следует помнить, что в системе может быть запущено более одного процесса с одним и тем же именем. Тем не менее, подобные агрегации помогают однозначно сказать, на что же тратится больше всего внимания: Скрипт: CODE: #!/usr/sbin/dtrace -s #pragma D option quiet syscall:::entry { self->ts=timestamp; } syscall:::return { self->elapsed = timestamp - self->ts; @time[execname]=sum(self->elapsed); } END { printf("\n%20s %20s\n", "Execname", "Time elapsed"); printa("%20s %20@u\n", @time); } Сохраните этот код в файл, сделайте ему chmod a+x и запускайте. Получите примерно такой результат: CODE: Execname Time elapsed xscreensaver 5710 gnome-smproxy 6886 wnck-applet 7735 gnome-panel 52032 metacity 54430 gnome-settings-d 60419 vim 66452 mixer_applet2 670078802 gnome-netstatus- 819836799 nautilus 900025830 Xorg 1074783431 gnome-terminal 1074816530 firefox-bin 2000076871 dtrace 9843796821648 Время в последней таблице приведено в наносекундах, так что не пугайтесь таким огромным числам :) Для засекания времени во время выполнения скрипта очень удобно использовать приведённую в примере переменную timestamp. Это счётчик наносекунд, который начинает отсчёт с произвольного числа, и потому может применяться только для относительных подсчётов времени. Вот тут-то и становится понятно, сколько всего ненужного происходит в секунду на моём лаптопе с запущенным Gnome ;) Далее можно немного усложнить скрипт, и получится мощный инструмент для подробного анализа, кто, чем, и как долго занимался: CODE: #!/usr/sbin/dtrace -s #pragma D option quiet syscall:::entry { self->ts=timestamp; } syscall:::return { self->elapsed = timestamp - self->ts; @time[execname,probefunc,pid,tid]=sum(self->elapsed); } END { printf("\n%20s %20s %8s %7s %20s\n", "Execname", "Syscall", "Process", "Thread", "Time elapsed"); printa("%20s %20s %8d %7d %20@u\n", @time); } Сохранив этот код в файл syscalls.d и запустив этот скрипт, вы получите примерно следующий результат (дабы не засорять блог, я удалил часть строк): CODE: Execname Syscall Process Thread Time elapsed gnome-terminal read 7199 1 12867 Xorg read 6953 1 13769 dtrace brk 7331 1 33647 dtrace schedctl 7331 1 39320 gnome-terminal write 7199 1 48052 Xorg writev 6953 1 57112 gnome-terminal pollsys 7199 1 646816 dtrace lwp_park 7331 1 44817217 Xorg pollsys 6953 1 46936244 dtrace ioctl 7331 1 9269224066655 Если оставить такой скрипт запущенным на пару минут, в результате получится длинный список, содержащий все процессы, запущенные в системе, со всеми системными вызовами, которые они выполняли, и с указанием времени, потраченного на эти вызовы каждым thread'ом. Defined tags for this entry: dtrace Обратные ссылки
URI этой записи для создания обратных ссылок (trackback)
Нет обратных ссылок
|




