ОПИСАНИЕ
Получая
список
параметров,
perf_event_open()
возвращает
файловый
дескриптор,
который
можно
использовать
в
последующих
вызовах (read(2),
mmap(2), prctl(2), fcntl(2) и т.
п.).
Вызов perf_event_open()
создаёт
файловый
дескриптор,
через
который
можно
получать
измерения
производительности.
Каждый
файловый
дескриптор
соответствует
одному
измеряемому
событию;
события
можно
группировать
для
одновременного
измерения.
События
можно
включать и
выключать
двумя
способами:
через ioctl(2) и
через prctl(2).
Когда
событие
отключено,
оно не
учитывается
и не
генерирует
переполнения,
но
продолжает
существовать
и
содержать
своё
значение
счётчика.
События
бывают
двух видов:
подсчитывающие
(counting) и
измеряющие
(sampled).
Подсчитывающее
событие
используется
для
сложения
числа
произошедших
событий.
Обычно,
результат
подсчёта
событий
выбирается
с помощью
вызова read(2).
Измеряющее
событие
периодически
пишет
значения
измерения
в буфер,
который
доступен
через
вызов mmap(2).
Аргументы
Аргументы
pid и cpu
позволяют
задать
отслеживаемый
процесс и
ЦП:
- pid == 0 и cpu
== -1
- Это
позволяет
измерять
вызывающий
процесс/нить
на любом
ЦП.
- pid == 0 и
cpu >= 0
- Это
позволяет
измерять
вызывающий
процесс/нить
только,
когда
выполнение
происходит
на
указанном
ЦП.
- pid > 0 и
cpu == -1
- Это
позволяет
измерять
указанный
процесс/нить
на любом
ЦП.
- pid > 0 и
cpu >= 0
- Это
позволяет
измерять
указанный
процесс/нить
только,
когда
выполнение
происходит
на
указанном
ЦП.
- pid == -1 и
cpu >= 0
- This measures all processes/threads on the specified CPU. This requires
CAP_PERFMON (since Linux 5.8) or CAP_SYS_ADMIN capability or
a /proc/sys/kernel/perf_event_paranoid value of less than 1.
- pid == -1 и
cpu == -1
- Это
некорректные
значения и
будет
возвращена
ошибка.
When pid is greater than zero, permission to perform this
system call is governed by CAP_PERFMON (since Linux 5.9) and a ptrace
access mode PTRACE_MODE_READ_REALCREDS check on older Linux versions;
see ptrace(2).
The group_fd argument allows event groups to be created. An
event group has one event which is the group leader. The leader is created
first, with group_fd = -1. The rest of the group members are created
with subsequent perf_event_open() calls with group_fd being
set to the file descriptor of the group leader. (A single event on its own
is created with group_fd = -1 and is considered to be a group with
only 1 member.) An event group is scheduled onto the CPU as a unit: it will
be put onto the CPU only if all of the events in the group can be put onto
the CPU. This means that the values of the member events can be meaningfully
compared—added, divided (to get ratios), and so on—with each
other, since they have counted events for the same set of executed
instructions.
Аргумент
flags
формируется
с помощью
объединения
логической
операцией
ИЛИ нуля
или более
следующих
значений:
- PERF_FLAG_FD_CLOEXEC
(начиная с Linux
3.14)
- Этот флаг
включает
флаг close-on-exec на
созданном
файловом
дескрипторе
события, то
есть
файловый
дескриптор
автоматически
закрывается
при execve(2).
Установка
флага close-on-exec
при
создании, а
не в
процессе
работы с
помощью fcntl(2),
позволяет
избежать
потенциальной
состязательности,
когда
вызывающая
нить
вызывает
perf_event_open() и fcntl(2)
одновременно
с запуском
другой
нитью
вызовов fork(2)
и execve(2).
- PERF_FLAG_FD_NO_GROUP
- Этот флаг
указывает
событию
игнорировать
параметр
group_fd, если не
выполняется
настройка
перенаправления
вывода с
помощью
флага PERF_FLAG_FD_OUTPUT.
- PERF_FLAG_FD_OUTPUT
(не
работает,
начиная с Linux
2.6.35)
- Этот флаг
переключает
вывод
измерений
с буфера mmap в
событие,
указанное
group_fd.
- PERF_FLAG_PID_CGROUP
(начиная с Linux
2.6.39)
- Этот флаг
включает
поконтейнерное
системное
слежение.
Контейнер
— это
абстракция,
которая
изолирует
набор
ресурсов
для их
точного
расходования
(ЦП, память
и т. п.). В этом
режиме
событие
измеряется
только,
если нить
выполняется
в
отслеживаемом
ЦП,
принадлежащем
назначенному
контейнеру
(cgroup). Значение
cgroup задаётся
переданным
файловым
дескриптором,
открываемом
в его
каталоге в
файловой
системе cgroupfs.
Например,
если
отслеживаемая
cgroup
называется
test, то
файловый
дескриптор
для /dev/cgroup/test
(предполагается,
что cgroupfs
смонтирована
в /dev/cgroup)
должен
передаваться
как
параметр
pid.
Слежение
за cgroup
доступно
только для
системных
событий и
поэтому
требуется
дополнительных
прав.
Структура
perf_event_attr
предоставляет
подробную
информацию
о
создаваемом
событии.
struct perf_event_attr {
__u32 type; /* тип события */
__u32 size; /* размер структуры атрибутов */
__u64 config; /* настройки для типа */
union {
__u64 sample_period; /* период выборки */
__u64 sample_freq; /* частота выборки */
};
__u64 sample_type; /* значения, включённые в измерение */
__u64 read_format; /* значения, возвращаемые при чтении */
__u64 disabled : 1, /* off by default */
inherit : 1, /* children inherit it */
pinned : 1, /* must always be on PMU */
exclusive : 1, /* only group on PMU */
exclude_user : 1, /* don't count user */
exclude_kernel : 1, /* don't count kernel */
exclude_hv : 1, /* don't count hypervisor */
exclude_idle : 1, /* don't count when idle */
mmap : 1, /* include mmap data */
comm : 1, /* include comm data */
freq : 1, /* use freq, not period */
inherit_stat : 1, /* per task counts */
enable_on_exec : 1, /* next exec enables */
task : 1, /* trace fork/exit */
watermark : 1, /* wakeup_watermark */
precise_ip : 2, /* skid constraint */
mmap_data : 1, /* non-exec mmap data */
sample_id_all : 1, /* sample_type all events */
exclude_host : 1, /* don't count in host */
exclude_guest : 1, /* don't count in guest */
exclude_callchain_kernel : 1,
/* exclude kernel callchains */
exclude_callchain_user : 1,
/* exclude user callchains */
mmap2 : 1, /* include mmap with inode data */
comm_exec : 1, /* flag comm events that are
due to exec */
use_clockid : 1, /* use clockid for time fields */
context_switch : 1, /* context switch data */
write_backward : 1, /* Write ring buffer from end
to beginning */
namespaces : 1, /* include namespaces data */
ksymbol : 1, /* include ksymbol events */
bpf_event : 1, /* include bpf events */
aux_output : 1, /* generate AUX records
instead of events */
cgroup : 1, /* include cgroup events */
text_poke : 1, /* include text poke events */
build_id : 1, /* use build id in mmap2 events */
inherit_thread : 1, /* children only inherit */
/* if cloned with CLONE_THREAD */
remove_on_exec : 1, /* event is removed from task
on exec */
sigtrap : 1, /* send synchronous SIGTRAP
on event */
__reserved_1 : 26;
union {
__u32 wakeup_events; /* пробуждаться каждые n событий */
__u32 wakeup_watermark; /* байт до пробуждения */
};
__u32 bp_type; /* тип точки останова */
union {
__u64 bp_addr; /* адрес точки останова */
__u64 kprobe_func; /* для perf_kprobe */
__u64 uprobe_path; /* для perf_uprobe */
__u64 config1; /* расширение of config */
};
union {
__u64 bp_len; /* breakpoint length */
__u64 kprobe_addr; /* with kprobe_func == NULL */
__u64 probe_offset; /* for perf_[k,u]probe */
__u64 config2; /* extension of config1 */
};
__u64 branch_sample_type; /* enum perf_branch_sample_type */
__u64 sample_regs_user; /* user regs to dump on samples */
__u32 sample_stack_user; /* size of stack to dump on
samples */
__s32 clockid; /* clock to use for time fields */
__u64 sample_regs_intr; /* regs to dump on samples */
__u32 aux_watermark; /* aux bytes before wakeup */
__u16 sample_max_stack; /* max frames in callchain */
__u16 __reserved_2; /* align to u64 */
__u32 aux_sample_size; /* max aux sample size */
__u32 __reserved_3; /* align to u64 */
__u64 sig_data; /* user data for sigtrap */
};
Описание
полей
структуры
perf_event_attr:
- type
- В этом поле
указывается
общий тип
события.
Может быть
одно из
следующих
значений:
- PERF_TYPE_HARDWARE
- Одно из
«общих»
аппаратных
событий,
предоставляется
ядром.
Подробней
смотрите в
описании
поля config.
- PERF_TYPE_SOFTWARE
- Одно из
программных
событий,
предоставляется
ядром
(даже, если
нет
аппаратной
поддержки).
- PERF_TYPE_TRACEPOINT
- Точка
трассировки,
предоставляется
ядерной
инфраструктурой
точек
трассировки.
- PERF_TYPE_HW_CACHE
- Событие
аппаратного
кэша.
Создаётся
специальным
кодированием,
смотрите
описание к
полю config.
- PERF_TYPE_RAW
- «Неструктурированное»,
определяемое
реализацией
событие из
поля config.
- PERF_TYPE_BREAKPOINT
(начиная с Linux
2.6.33)
- Аппаратная
точка
останова,
предоставляемая
ЦП. Точки
останова
можно
настроить
на событие
чтения/записи
по адресу,
а также на
выполнение
инструкции
по
определённому
адресу.
- динамический
PMU
- Начиная с Linux
2.6.38, perf_event_open()
поддерживает
несколько
PMU. Чтобы
задать
используемый
PMU, его
указывают
в значении
type,
экспортируемое
ядром.
Нужное
значение
можно
найти в
файловой
системе sysfs:
для
каждого
экземпляра
PMU
создаётся
подкаталог
в каталоге
/sys/bus/event_source/devices. В
каждом
подкаталоге
есть файл
type,
содержащий
целое
число,
которое
можно
использовать
в поле type.
Например, в
/sys/bus/event_source/devices/cpu/type
содержится
значение
для PMU ядра
ЦП,
которое,
обычно
равно 4.
- kprobe и
uprobe (начиная
с Linux 4.17)
- Эти два
динамических
PMU создают kprobe/uprobe
и
присоединяют
к
файловому
дескриптору,
сгенерованному
perf_event_open. kprobe/uprobe будет
уничтожен
при
уничтожении
файлового
дескриптора.
Подробности
смотрите в
описании
полей kprobe_func,
uprobe_path, kprobe_addr и probe_offset.
- size
- Размер
структуры
perf_event_attr
совместимости.
Присвоение
значения
sizeof(struct perf_event_attr)
позволяет
ядру
видеть
размер
структуры
во время
компиляции.
- Соответствующее
определение
PERF_ATTR_SIZE_VER0 равно 64;
это размер
первой
опубликованной
структуры.
Значение
PERF_ATTR_SIZE_VER1 равно 72,
соответствует
добавленным
в Linux 2.6.33 точкам
останова.
Значение
PERF_ATTR_SIZE_VER2 равно 80,
соответствует
добавленным
в Linux 3.4 ветвям
замеров.
Значение
PERF_ATTR_SIZE_VER3 равно 96,
соответствует
добавленным
в Linux 3.7 полям
sample_regs_user и sample_stack_user.
Значение
PERF_ATTR_SIZE_VER4 равно 104,
соответствует
добавленному
в Linux 3.19 полю
sample_regs_intr.
Значение
PERF_ATTR_SIZE_VER5 равно 112,
соответствует
добавленному
в in Linux 4.1 полю
aux_watermark.
- config
- Здесь
указывается
требуемое
событие в
сочетании
с полем type.
Поля config1 и config2
также
учитываются,
если 64 бит
недостаточно
для
полного
описания
события.
Кодирование
значения
этих полей
зависит от
события.
- Есть
несколько
способов
присвоения
значения
полю config,
которые
зависят от
значения
описанного
ранее поля
type.
Содержимое
различных
возможных
настроек
config
выделяется
по type.
- Если type
равно PERF_TYPE_HARDWARE,
то
измеряется
одно из
общих
аппаратных
событий ЦП.
Не все из
них
доступны
на всех
платформах.
В config может
быть одно
из
следующих
значений:
- Если
значение
type равно
PERF_TYPE_SOFTWARE, то
измеряются
программные
события,
предоставляемые
ядром.
Значением
config может
быть одно
из
следующих:
- PERF_COUNT_SW_CPU_CLOCK
- Сообщить о
часах ЦП,
таймере
высокого
разрешения,
работающем
на каждом
ЦП.
- PERF_COUNT_SW_TASK_CLOCK
- Сообщить о
часах
выполняющейся
задачи.
- PERF_COUNT_SW_PAGE_FAULTS
- Сообщить о
количестве
сбойных
страниц.
- PERF_COUNT_SW_CONTEXT_SWITCHES
- Подсчёт
числа
переключений
контекста.
До Linux 2.6.34, это
считалось
событиями
пользовательского
пространства,
теперь об
этом
сообщается
как о
происходящем
в ядре.
- PERF_COUNT_SW_CPU_MIGRATIONS
- Сообщить
сколько
раз
процесс
перемещался
в другой
ЦП.
- PERF_COUNT_SW_PAGE_FAULTS_MIN
- Сообщить о
количестве
незначительных
промахов
страниц.
Они не
связаны с
обработкой
дисковых
операций
ввода-вывода.
- PERF_COUNT_SW_PAGE_FAULTS_MAJ
- Сообщить о
количестве
значительных
промахов
страниц.
Они
связаны с
обработкой
дисковых
операций
ввода-вывода.
- PERF_COUNT_SW_ALIGNMENT_FAULTS
(начиная с Linux
2.6.33)
- Сообщить о
количестве
ошибок
выравнивания.
Они
возникают,
когда
происходит
доступ к
памяти по
невыровненному
адресу;
ядро может
обработать
такую
ситуацию,
но это
снижает
производительность.
Бывает
только на
некоторых
архитектурах
(на x86 —
никогда).
- PERF_COUNT_SW_EMULATION_FAULTS
(начиная с Linux
2.6.33)
- Сообщить о
количестве
ошибок
эмуляции.
Ядро
иногда
попадает в
ловушки
нереализованных
инструкций
и
эмулирует
их в
пользовательском
пространстве.
Это может
негативно
отражаться
на
производительности.
- PERF_COUNT_SW_DUMMY
(начиная с Linux
3.12)
- Заместитель
события,
которое
ничего не
подсчитывает.
This is a placeholder event that counts nothing.
Информационные
образцы
типов
записей,
таких как mmap
или comm,
должны
быть
связаны с
активным
событием.
Данное
пустое
событие
позволяет
собирать
такие
записи без
необходимости
в
подсчитывающем
событии.
- PERF_COUNT_SW_BPF_OUTPUT
(since Linux 4.4)
- This is used to generate raw sample data from BPF. BPF programs can write
to this event using bpf_perf_event_output helper.
- PERF_COUNT_SW_CGROUP_SWITCHES
(since Linux 5.13)
- This counts context switches to a task in a different cgroup. In other
words, if the next task is in the same cgroup, it won't count the
switch.
Если type
равно PERF_TYPE_TRACEPOINT,
то
измеряется
точки
трассировки
ядра.
Значение,
используемое
в config, можно
получить
из debugfs tracing/events/*/*/id,
если ftrace
включён в
ядре.
Если
type
равно
PERF_TYPE_HW_CACHE,
то
измеряется
событие
кэша
аппаратного
ЦП. Для
вычисления
соответствующего
значения
config
используйте
следующую
формулу:
config = (perf_hw_cache_id) |
(perf_hw_cache_op_id << 8) |
(perf_hw_cache_op_result_id << 16);
где perf_hw_cache_id
одно из:
и perf_hw_cache_op_id
одно из:
и perf_hw_cache_op_result_id
одно из:
Если type
равно PERF_TYPE_RAW,
то
требуется
пользовательское
«неструктурированное»
значение
config.
Большинство
ЦП
поддерживают
события,
которые не
подпадают
под
«общие»
события.
Они
определяются
реализацией;
смотрите
руководство
на ЦП
(например,
документацию
Intel Volume 3B или AMD BIOS и
руководство
разработчика
ядра). Для
трансляции
ожидаемых
значений в
этом поле
шестнадцатеричных
значений в
perf_event_open() из имён
справочников
по
архитектуре
можно
использовать
библиотеку
libpfm4.
Если type
равно PERF_TYPE_BREAKPOINT,
то
присвойте
config
значение 0.
Его
параметры
задаются в
других
местах.
Если type
равно kprobe
или uprobe,
установите
retprobe (бит 0 в config,
смотрите
/sys/bus/event_source/devices/[k,u]probe/format/retprobe)
равным kretprobe/uretprobe.
Дополнительную
информацию
смотрите в
описании
полей kprobe_func,
uprobe_path, kprobe_addr и probe_offset.
- kprobe_func,
uprobe_path, kprobe_addr и probe_offset
- Эти поля
описывают
kprobe/uprobe в
динамических
PMU kprobe и uprobe. Для
kprobe:
используйте
kprobe_func и probe_offset, или
используйте
kprobe_addr и
оставьте
kprobe_func равным NULL.
Для uprobe:
используйте
uprobe_path и probe_offset.
- sample_period,
sample_freq
- «Измеряющее»
событие
генерирует
уведомление
о
переполнении
каждые N
событий,
где N
указывается
в sample_period. У
измеряющего
события
sample_period > 0. Если
происходит
переполнение,
то
запрашиваемые
данные
записываются
в буфер mmap. В
поле sample_type
указывается
какие
данные
записываются
при каждом
переполнении.
- Если вы
хотите
использовать
частоту, а
не период,
то можно
использовать
sample_freq. В этом
случае
установите
флаг freq.
Ядро
откорректирует
период
измерений,
чтобы
попытаться
достигнуть
желаемой
частоты.
Частота
измеряется
в тактах
таймера.
- sample_type
- Различными
битами
этого поля
определяется
какие
значения
включать в
измерение.
Они будут
записаны в
кольцевой
буфер,
который
доступен в
пользовательском
пространстве
через mmap(2).
Порядок
сохраняемых
значений
описан в
разделе
«Разбивка
MMAP» ниже; он
не
совпадает
с порядком
enum perf_event_sample_format.
- PERF_SAMPLE_IP
- Сохранять
указатель
инструкций.
- PERF_SAMPLE_TID
- Сохранять
идентификатор
процесса и
нити.
- PERF_SAMPLE_TIME
- Сохранять
метку
времени.
- PERF_SAMPLE_ADDR
- Сохранять
адрес (если
используется).
- PERF_SAMPLE_READ
- Сохранять
значения
счётчика
для всех
событий в
группе, а
не только
для лидера
группы.
- PERF_SAMPLE_CALLCHAIN
- Сохранять
цепочку
вызовов
(обратная
трассировка
стека).
- PERF_SAMPLE_ID
- Сохранять
уникальный
идентификатор
для
открытых
лидером
группы
событий.
- PERF_SAMPLE_CPU
- Сохранять
номер ЦП.
- PERF_SAMPLE_PERIOD
- Сохранять
текущий
период
измерения.
- PERF_SAMPLE_STREAM_ID
- Сохранять
уникальный
идентификатор
открытого
события. В
отличии от
PERF_SAMPLE_ID
возвращается
реальный
идентификатор,
а не лидера
группы.
Этот же
идентификатор
возвращается
PERF_FORMAT_ID.
- PERF_SAMPLE_RAW
- Сохранять
дополнительные
данные,
если есть.
Обычно
возвращаются
для
событий
трассировки.
- PERF_SAMPLE_BRANCH_STACK
(начиная с Linux
3.4)
- Сохранять
запись о
новых
ветвях,
предоставляемых
аппаратурой
ветвления
ЦП
(например, Intel
Last Branch Record). Не
каждая
аппаратура
поддерживает
данную
возможность.
- В описании
поля branch_sample_type
показано
как
выбирать
ветви, о
которых
нужно
сообщать.
- PERF_SAMPLE_REGS_USER
(начиная с Linux
3.7)
- Записывать
текущее
состояние
регистров
ЦП на
уровне
пользователя
(значения в
процессе
до вызова
ядра).
- PERF_SAMPLE_STACK_USER
(начиная с Linux
3.7)
- Сохранять
стек
пользовательского
уровня для
размотки
стека.
- PERF_SAMPLE_WEIGHT
(начиная с Linux
3.10)
- Сохранять
данные
аппаратуры,
предоставляющие
весовое
значение,
которое
отражает
насколько
затратным
было
измеряемое
событие.
Это
позволяет
аппаратуре
выявлять
затратные
события в
профиле.
- PERF_SAMPLE_DATA_SRC
(начиная с Linux
3.10)
- Сохранять
источник
данных: где
в иерархии
памяти
находятся
данные,
связанные
с
измеряемое
инструкцией.
Доступно
только,
если
поддерживается
аппаратурой.
- PERF_SAMPLE_IDENTIFIER
(начиная с Linux
3.12)
- Помещать
значение
SAMPLE_ID в
фиксированном
месте
записи, или
в начале
(для
измеряемых
событий)
или в конце
(для не
измеряемого
события).
- Это было
необходимо
потому, что
поток
измерений
может
содержать
записи из
различных
источников
событий с
различными
параметрами
sample_type.
Корректный
разбор
потока
событий
невозможен,
так как для
формата
записи
необходимо
найти SAMPLE_ID,
но формат
невозможно
определить
без
значения
какому
измерению
принадлежит
событие
(что
вызывает
циклическую
зависимость).
- Значение
PERF_SAMPLE_IDENTIFIER
делает
поток
всегда
анализируемым,
помещая SAMPLE_ID
в
фиксированное
расположение,
несмотря
на уже
имеющиеся
значения
SAMPLE_ID в
записях.
- PERF_SAMPLE_TRANSACTION
(начиная с Linux
3.13)
- Сохранять
причины
событий
аварий
транзакционной
памяти
(например,
из
поддержки
транзакционной
памяти Intel TSX).
- Значение
precise_ip должно
быть
больше 0 и
должно
измеряться
событие
аварии
транзакционной
памяти или
значения
не будут
записаны.
Также
отметим,
что
некоторые
измерения
perf_event, такие
как
подсчёт
числа
циклов,
могут
приводить
к
дополнительным
авариям
(вызванным
прерыванием
во время
транзакции).
- PERF_SAMPLE_REGS_INTR
(начиная с Linux
3.19)
- Сохранять
поднабор
текущего
состояния
регистров
ЦП, который
определяется
sample_regs_intr. В
отличии от
PERF_SAMPLE_REGS_USER будут
возвращены
значения
регистров
из
состояния
ядра, если
произойдёт
переполнение
при
выполнении
кода ядра.
Если ЦП
аппаратно
поддерживает
измерение
состояния
регистра (PEBS
в Intel x86) и precise_ip
больше
нуля, то
возвращаются
значения
регистров,
захваченных
аппаратурой
во время
измерения
запоздалой
инструкции.
- PERF_SAMPLE_PHYS_ADDR
(начиная с Linux
4.13)
- Records physical address of data like in PERF_SAMPLE_ADDR.
- PERF_SAMPLE_CGROUP
(начиная с Linux
5.7)
- Records (perf_event) cgroup ID of the process. This corresponds to the
id field in the PERF_RECORD_CGROUP event.
- PERF_SAMPLE_DATA_PAGE_SIZE
(since Linux 5.11)
- Records page size of data like in PERF_SAMPLE_ADDR.
- PERF_SAMPLE_CODE_PAGE_SIZE
(since Linux 5.11)
- Records page size of ip like in PERF_SAMPLE_IP.
- PERF_SAMPLE_WEIGHT_STRUCT
(since Linux 5.12)
- Records hardware provided weight values like in PERF_SAMPLE_WEIGHT,
but it can represent multiple values in a struct. This shares the same
space as PERF_SAMPLE_WEIGHT, so users can apply either of those,
not both. It has the following format and the meaning of each field is
dependent on the hardware implementation.
union perf_sample_weight {
u64 full; /* PERF_SAMPLE_WEIGHT */
struct { /* PERF_SAMPLE_WEIGHT_STRUCT */
u32 var1_dw;
u16 var2_w;
u16 var3_w;
};
};
- read_format
- В этом поле
задаётся
формат
данных,
возвращаемых
read(2) из
файлового
дескриптора
perf_event_open().
- PERF_FORMAT_TOTAL_TIME_ENABLED
- Добавлять
64-битное
поле time_enabled.
Его можно
использовать
для
вычисления
общей
оценки,
если PMU
слишком
загружено
и возникло
мультиплексирование.
- PERF_FORMAT_TOTAL_TIME_RUNNING
- Добавлять
64-битное
поле time_running.
Его можно
использовать
для
вычисления
общей
оценки,
если PMU
слишком
загружено
и возникло
мультиплексирование.
- PERF_FORMAT_ID
- Добавлять
64-битное
уникальное
значение,
которое
соответствует
группе
событий.
- PERF_FORMAT_GROUP
- Позволить
все
значения
счётчиков
в группе
событий
читать за
один
проход.
- PERF_FORMAT_LOST
(since Linux 6.0)
- Adds a 64-bit value that is the number of lost samples for this event.
This would be only meaningful when sample_period or
sample_freq is set.
- disabled
- Битом disabled
определяется,
будет ли
счётчик
изначально
включен
или
выключен.
Если
выключен,
то событие
может быть
включено
позже с
помощью ioctl(2),
prctl(2) или enable_on_exec.
- Обычно, при
создании
группы
событий
значение
disabled лидера
группы
устанавливается
в 1, а у
любого
дочернего
события disabled
устанавливается
в 0.
Несмотря
на disabled
равное 0,
дочерние
события не
запускаются
до тех пор,
пока не
включится
лидер
группы.
- inherit
- Битом inherit
задаётся,
должен ли
этот
счётчик
событий
считать
события
дочерних
задач,
кроме
указанной
задачи. Это
применяется
только к
новым
потомкам, а
не к
существующим
на момент
создания
счётчика (и
не к новым
потомкам
существующих
потомков).
- Наследование
не
работает с
некоторыми
комбинациями
значений
read_format,
например с
PERF_FORMAT_GROUP.
- pinned
- Битом pinned
определяется,
что
счётчик
должен
всегда
быть на ЦП,
если это
возможно.
Применяется
только к
аппаратным
счётчикам
и только
для
лидеров
группы.
Если
прикреплённый
счётчик
невозможно
поместить
на ЦП
(например,
потому что
кончились
аппаратные
счётчики
или возник
конфликт с
другим
событием),
то счётчик
переводится
в
состояние
«ошибки», в
котором
чтение
возвращает
конец
файла (т. е.,
read(2)
возвращает
0) до тех пор,
пока
счётчик не
будет
включен
или
выключен.
- exclusive
- Битом exclusive
определяется,
что когда
эта группа
счётчиков
на ЦП, то
должна
быть
только
одна
группа
использующая
счётчики
ЦП. В
будущем,
это может
позволить
следящим
программам
поддерживать
возможности
PMU,
необходимые
для
автономной
работы без
нарушения
других
аппаратных
счётчиков.
- Заметим,
что многие
неожиданные
ситуации
могут не
позволить
событиям с
битом exclusive
даже
выполниться.
К ним
относятся
выполнение
любых
пользовательских
системных
измерений,
а также
использование
ядром
счётчиков
производительности
(включая
обычно
включённый
интерфейс
NMI Watchdog Timer).
- exclude_user
- Если этот
бит
установлен,
то счётчик
не
учитывает
события,
происходящие
в
пользовательском
пространстве.
- exclude_kernel
- Если этот
бит
установлен,
то счётчик
не
учитывает
события,
происходящие
в
пространстве
ядра.
- exclude_hv
- Если этот
бит
установлен,
то счётчик
не
учитывает
события,
происходящие
в
гипервизоре.
В основном
для PMU,
имеющего
для этого
возможности
(такие как POWER).
На
большинстве
машин
необходима
дополнительная
поддержка
для
измерений
гипервизора.
- exclude_idle
- Если
установлен,
то счётчик
не
учитывает
когда ЦП
выполняет
задачу
простоя.
Хотя
сейчас вы и
можете
включить
его для
любого
типа
события, он
игнорируется
во всех
кроме
программных
событий.
- mmap
- Бит mmap
включает
генерацию
измерений
PERF_RECORD_MMAP для
каждого
вызова mmap(2) с
установленными
битом PROT_EXEC.
Это
позволяет
инструментам
замечать
новый
исполняемый
код,
отображённый
в
программу
(например,
общие
динамические
библиотеки)
так, чтобы
адреса
можно было
отобразить
обратно в
первоначальный
код.
- comm
- Битом comm
включается
слежение
за именем
команды
процесса,
изменяемого
системными
вызовами
execve(2) и prctl(PR_SET_NAME), а
также
через
запись в
/proc/self/comm. Если
флаг comm_exec
также
установлен
(работает,
начиная с Linux
3.16), то можно
использовать
вспомогательный
флаг PERF_RECORD_MISC_COMM_EXEC,
чтобы
отличить
использование
execve(2) от
остальных.
- freq
- Если этот
бит
установлен,
то задания
интервала
измерения
используется
sample_frequency, а не
sample_period.
- inherit_stat
- Этот бит
включает
сохранение
счётчика
событий
при
переключении
контекста
для
наследуемых
задач. Это
полезно
только,
если
установлен
бит inherit.
- enable_on_exec
- Если этот
бит
установлен,
то счётчик
автоматически
включается
после
вызова execve(2).
- task
- Если этот
бит
установлен,
то в
кольцевой
буфер
включаются
уведомления
fork/exit.
- watermark
- Если
установлен,
то
выдаётся
уведомление
о
переполнении
при
пересечении
границы
wakeup_watermark. В
противном
случае,
уведомления
о
переполнении
выдаются
после wakeup_events
измерений.
- precise_ip
(начиная с Linux
2.6.35)
- Управляет
размером
ската (skid).
Скат —
количество
инструкций,
выполняемое
между
возникновением
интересующего
события и
когда ядро
способно
остановиться
и записать
событие.
Чем меньше
скат тем
лучше: это
приближает
события к
инструкциям,
от которых
они
возникли,
но часто
значение
ограничивается
аппаратурой.
- Возможными
значениями
этого поля
могут
быть:
- 0
- SAMPLE_IP может
иметь
произвольный
скат.
- 1
- SAMPLE_IP должен
иметь
постоянный
скат.
- 2
- SAMPLE_IP
запрашивает
нулевой
скат.
- 3
- Значение
SAMPLE_IP должно
иметь 0
скат (skid).
Смотрите
также
описание I
в PERF_RECORD_MISC_EXACT_IP().
- mmap_data
(начиная с Linux
2.6.36)
- Противоположно
полю mmap.
Включает
генерацию
измерений
PERF_RECORD_MMAP для
вызовов mmap(2),
у которых
не
установлен
бит PROT_EXEC
(например,
у данных и
общей
памяти SysV).
- sample_id_all
(начиная с Linux
2.6.38)
- Если
установлен,
то TID, TIME, ID, STREAM_ID и ЦП
могут
дополнительно
включаться
в не-PERF_RECORD_SAMPLE,
если
выбран
соответствующий
sample_type.
- Если
указан
PERF_SAMPLE_IDENTIFIER, то
дополнительно
включается
значение ID
в качестве
последнего
значения
для
облегчения
разбора
потока
записей.
Это может
привести к
появлению
значения id
дважды.
- Состав
описывается
следующей
псевдо-структурой:
-
struct sample_id {
{ u32 pid, tid; } /* если есть PERF_SAMPLE_TID */
{ u64 time; } /* если есть PERF_SAMPLE_TIME */
{ u64 id; } /* если есть PERF_SAMPLE_ID */
{ u64 stream_id;} /* если есть PERF_SAMPLE_STREAM_ID */
{ u32 cpu, res; } /* если есть PERF_SAMPLE_CPU */
{ u64 id; } /* если есть PERF_SAMPLE_IDENTIFIER */
};
- exclude_host
(начиная с Linux
3.2)
- При
проведении
измерений,
которые
включают
процессы,
запускающие
экземпляры
VM (т. е.
выполняют I
ioctl(2) KVM_RUN),
измеряются
только
события,
возникающие
внутри
гостевого
экземпляра.
Имеет
смысл
только вне
гостевых
машин; эта
настройка
не
изменяет
счётчики,
собираемые
внутри
гостей. В
настоящее
время
работает
только на
x86.
- exclude_guest
(начиная с Linux
3.2)
- При
проведении
измерений,
которые
включают
процессы,
запускающие
экземпляры
VM (т. е.
выполняют I
ioctl(2) KVM_RUN), не
измеряются
события,
возникающие
внутри
гостевого
экземпляра.
Имеет
смысл
только вне
гостевых
машин; эта
настройка
не
изменяет
счётчики,
собираемые
внутри
гостей. В
настоящее
время
работает
только на
x86.
- exclude_callchain_kernel
(начиная с Linux
3.7)
- Не
включать
цепочку
вызовов
ядра.
- exclude_callchain_user
(начиная с Linux
3.7)
- Не
включать
цепочку
вызовов
пользовательского
пространства.
- mmap2
(начиная с Linux
3.16)
- Генерировать
расширенную
запись
выполняемого
mmap, которая
содержит
дополнительную
информацию,
достаточную
для
определения
уникальности
общих
отображений.
Для работы
также
требуется
установить
флаг mmap.
- comm_exec
(начиная с Linux
3.16)
- Флаг
определения
свойств, не
изменяет
поведение
ядра. Если
флаг
установлен,
то когда
включён comm,
будет
устанавливаться
флаг PERF_RECORD_MISC_COMM_EXEC
в поле misc
заголовка
записи comm,
если
сообщается
о событии
переименования,
вызванного
вызовом execve(2).
Это
позволяет
инструментам
различать
различные
тип
переименования
процесса.
- use_clockid
(начиная с Linux
4.1)
- Через clockid
позволяет
выбрать
внутренние
часы Linux,
используемые
для
генерации
меток
времени.
Это может
облегчить
соответствие
времён
измерений
с метками
времени,
сгенерированными
другими
инструментами.
- context_switch
(начиная с Linux
4.3)
- Включает
генерацию
записей
PERF_RECORD_SWITCH при
переключении
контекста.
Также
включает
генерацию
записей
PERF_RECORD_SWITCH_CPU_WIDE при
измерении
в режиме CPU-wide.
Данная
возможность
дополняет
существующие
точки
трассировки
и
программные
события
для
измерения
переключений
контекста.
Преимущество
этого
метода в
том, что он
даёт
полную
информацию
даже при
ограничительных
настройках
perf_event_paranoid.
- write_backward
(начиная с Linux
4.6)
- This causes the ring buffer to be written from the end to the beginning.
This is to support reading from overwritable ring buffer.
- namespaces
(начиная с Linux
4.11)
- This enables the generation of PERF_RECORD_NAMESPACES records when
a task enters a new namespace. Each namespace has a combination of device
and inode numbers.
- ksymbol
(начиная с Linux
5.0)
- This enables the generation of PERF_RECORD_KSYMBOL records when new
kernel symbols are registered or unregistered. This is analyzing dynamic
kernel functions like eBPF.
- bpf_event
(начиная с Linux
5.0)
- This enables the generation of PERF_RECORD_BPF_EVENT records when
an eBPF program is loaded or unloaded.
- aux_output
(since Linux 5.4)
- This allows normal (non-AUX) events to generate data for AUX events if the
hardware supports it.
- cgroup
(начиная с Linux
5.7)
- This enables the generation of PERF_RECORD_CGROUP records when a
new cgroup is created (and activated).
- text_poke
(начиная с Linux
5.8)
- This enables the generation of PERF_RECORD_TEXT_POKE records when
there's a change to the kernel text (i.e., self-modifying code).
- build_id (since
Linux 5.12)
- This changes the contents in the PERF_RECORD_MMAP2 to have a
build-id instead of device and inode numbers.
- inherit_thread
(since Linux 5.13)
- This disables the inheritance of the event to a child process. Only new
threads in the same process (which is cloned with CLONE_THREAD)
will inherit the event.
- remove_on_exec
(since Linux 5.13)
- This closes the event when it starts a new process image by
execve(2).
- sigtrap (since
Linux 5.13)
- This enables synchronous signal delivery of SIGTRAP on event
overflow.
- wakeup_events,
wakeup_watermark
- Это
объединение
задаёт как
много
измерений
(wakeup_events) или
байт (wakeup_watermark)
должно
произойти
до
уведомления
о
переполнении.
Используемое
поле
выбирается
битом
флага watermark.
- В wakeup_events
подсчитываются
только
записи с
типом PERF_RECORD_SAMPLE.
Для приёма
уведомления
о
переполнении
всех типов
PERF_RECORD
выберите watermark
и
присвойте
wakeup_watermark
значение 1.
- До Linux 3.0
установка
wakeup_events в 0
приводила
к
выключению
уведомления
о
переполнении;
новые ядра
считают 0
как 1.
- bp_type
(начиная с Linux
2.6.33)
- Задаёт тип
точки
останова.
Может
быть:
- HW_BREAKPOINT_EMPTY
- Нет точки
останова.
- HW_BREAKPOINT_R
- Считать,
когда
выполняется
чтение из
определённого
места
памяти.
- HW_BREAKPOINT_W
- Считать,
когда
выполняется
запись в
определённое
место
памяти.
- HW_BREAKPOINT_RW
- Считать,
когда
выполняется
чтение или
запись в
определённое
место
памяти.
- HW_BREAKPOINT_X
- Считать,
когда
выполняется
код из
определённого
места
памяти.
Значения
можно
побитово
объединять,
но
комбинация
HW_BREAKPOINT_R или HW_BREAKPOINT_W
с HW_BREAKPOINT_X
недопустима.
- bp_addr
(начиная с Linux
2.6.33)
- Адрес
точки
останова.
Для точек
останова
выполнения
это адрес
памяти
интересующей
инструкции;
для точек
останова
чтения и
записи это
адрес
памяти
интересующего
расположения
в памяти.
- config1
(начиная с Linux
2.6.39)
- Значение
config1
используется
для
задания
событий,
которым
нужен
дополнительный
регистр
или не
хватает
обычного
поля config. Это
поле
используется
в Linux 3.3 и новее
для
неструктурированного
OFFCORE_EVENTS на
архитектурах
Nehalem/Westmere/SandyBridge.
- bp_len
(начиная с Linux
2.6.33)
- В bp_len
содержится
длина
точки
измеряемой
останова,
если
значение
type равно
PERF_TYPE_BREAKPOINT. Можно
указывать
HW_BREAKPOINT_LEN_1, HW_BREAKPOINT_LEN_2,
HW_BREAKPOINT_LEN_4 и HW_BREAKPOINT_LEN_8.
Для точки
останова
выполнения
присвойте
sizeof(long).
- config2
(начиная с Linux
2.6.39)
- Поле config2 —
дальнейшее
расширение
поля config1.
- branch_sample_type
(начиная с Linux
3.4)
- Если
установлен
PERF_SAMPLE_BRANCH_STACK, то
ветви
будут
включаться
в запись
ветви.
- В первой
части
значения
задаётся
уровень
привилегий,
который
может быть
комбинацией
одного из
показанных
ниже
значений.
Если
пользователь
явно не
задал
уровень
привилегий,
то ядро
будет
использовать
уровень
привилегий
события.
Событие и
уровни
привилегий
ветви не
совпадают.
- sample_regs_user
(начиная с Linux
3.7)
- Данной
битовой
маской
задаётся
набор
битов
пользовательских
регистров
ЦП, которые
сохраняются
в
измерениях.
Значения
битов в
битовой
маске
зависят от
архитектуры
и описаны в
заголовочном
файле ядра
arch/ARCH/include/uapi/asm/perf_regs.h.
- sample_stack_user
(начиная с Linux
3.7)
- Задаёт
размер
сохраняемого
пользовательского
стека, если
указан
PERF_SAMPLE_STACK_USER.
- clockid
(начиная с Linux
4.1)
- Если
установлен
use_clockid, то этим
полем
выбирается
внутренний
таймер Linux,
используемый
для меток
времени.Доступные
таймеры
определены
в linux/time.h; в
настоящее
время
поддерживаются
CLOCK_MONOTONIC, CLOCK_MONOTONIC_RAW, CLOCK_REALTIME,
CLOCK_BOOTTIME и CLOCK_TAI.
- aux_watermark
(начиная с Linux
4.1)
- Определяет
какое
количество
данных
требуется
для
запуска
измерения
PERF_RECORD_AUX.
- sample_max_stack
(начиная с Linux
4.8)
- Если sample_type
содержит
PERF_SAMPLE_CALLCHAIN, то в
этом поле
задаётся
количество
выводимых
кадров
стека при
генерации
цепочки
вызовов.
- aux_sample_size
(since Linux 5.5)
- When PERF_SAMPLE_AUX flag is set, specify the desired size of AUX
data. Note that it can get smaller data than the specified size.
- sig_data (since
Linux 5.13)
- This data will be copied to user's signal handler (through si_perf
in the siginfo_t) to disambiguate which event triggered the
signal.
Чтение
результатов
После
открытия
файлового
дескриптора
с помощью
perf_event_open(),
значения
событий
доступны
на чтение.
События
задаются
вв поле read_format
структуры
attr в момент
открытия.
Если вы
попытаетесь
выполнить
чтение в
буфер
недостаточного
размера, то
результатом
будет
ошибка ENOSPC.
Вот
компоновка
данных,
возвращаемых
чтением:
- •
- Если
указан PERF_FORMAT_GROUP
для
разрешения
чтения
всех
событий в
группе за
раз:
-
struct read_format {
u64 nr; /* The number of events */
u64 time_enabled; /* if PERF_FORMAT_TOTAL_TIME_ENABLED */
u64 time_running; /* if PERF_FORMAT_TOTAL_TIME_RUNNING */
struct {
u64 value; /* The value of the event */
u64 id; /* if PERF_FORMAT_ID */
u64 lost; /* if PERF_FORMAT_LOST */
} values[nr];
};
- •
- Если PERF_FORMAT_GROUP
не
указан:
-
struct read_format {
u64 value; /* The value of the event */
u64 time_enabled; /* if PERF_FORMAT_TOTAL_TIME_ENABLED */
u64 time_running; /* if PERF_FORMAT_TOTAL_TIME_RUNNING */
u64 id; /* if PERF_FORMAT_ID */
u64 lost; /* if PERF_FORMAT_LOST */
};
Значения
полей:
- nr
- Количество
событий в
этом
файловом
дескрипторе.
Доступно
только,
если
указан
PERF_FORMAT_GROUP.
- time_enabled,
time_running
- Полное
время
события с
момента
включения
и
выполнения.
Обычно, эти
значения
одинаковы.
Если
событий
больше, чем
доступно
счётчиков
слотов в PMU,
то
возникает
мультиплексирование.
В этом
случае
события
выполняются
только
часть
времени и
значения
time_enabled и time running
можно
использовать
для
градации
рассчитанного
значения в
счётчике.
- value
- Целое
беззнаковое
64-битное
значение,
содержащее
счётчик-результат.
- id
- Глобально
уникальное
значение
данного
события;
присутствует
только,
если в read_format
указан
PERF_FORMAT_ID.
- lost
- The number of lost samples of this event; only present if
PERF_FORMAT_LOST was specified in read_format.
Разбивка
MMAP
При
использовании
perf_event_open() в
режиме
измерений,
асинхронные
события
(такие как
переполнение
счётчика
или
слежение
за PROT_EXEC mmap)
протоколируются
в
кольцевой
буфер. Этот
кольцевой
буфер
создаётся
и доступен
через mmap(2).
The mmap size should be 1+2^n pages, where the first page is a
metadata page (struct perf_event_mmap_page) that contains various
bits of information such as where the ring-buffer head is.
Before Linux 2.6.39, there is a bug that means you must allocate
an mmap ring buffer when sampling even if you do not plan to access it.
Структура
первой
страницы
метаданных
mmap:
struct perf_event_mmap_page {
__u32 version; /* номер версии структуры */
__u32 compat_version; /* наименьшая совместимая версия */
__u32 lock; /* seqlock для синхронизации */
__u32 index; /* идентификатор аппаратного счётчика */
__s64 offset; /* добавляется к значению аппаратного
счётчика */
__u64 time_enabled; /* время активности события */
__u64 time_running; /* время события на ЦП */
union {
__u64 capabilities;
struct {
__u64 cap_usr_time / cap_usr_rdpmc / cap_bit0 : 1,
cap_bit0_is_deprecated : 1,
cap_user_rdpmc : 1,
cap_user_time : 1,
cap_user_time_zero : 1,
};
};
__u16 pmc_width;
__u16 time_shift;
__u32 time_mult;
__u64 time_offset;
__u64 __reserved[120]; /* дополнение до 1 k */
__u64 data_head; /* заголовок в секции данных */
__u64 data_tail; /* хвост, записываемый из
пользовательского пространства */
__u64 data_offset; /* начало буфера */
__u64 data_size; /* размер буфера данных */
__u64 aux_head;
__u64 aux_tail;
__u64 aux_offset;
__u64 aux_size;
}
В
следующем
списке
поля
структуры
perf_event_mmap_page
описаны
более
подробно:
- version
- Номер
версии
этой
структуры.
- compat_version
- Наименьший
номер
версии,
совместимой
с данной
структурой.
- lock
- Значение seqlock
для
синхронизации.
- index
- Уникальный
идентификатор
аппаратного
счётчика.
- offset
- При
использовании
rdpmc для
чтения это
значение
смещения
должно
добавляться
к
возвращаемому
rdpmc для
получения
текущего
общего
количества
событий.
- time_enabled
- Время
активности
события.
- time_running
- Время
выполнения
события.
- cap_usr_time
/ cap_usr_rdpmc / cap_bit0
(начиная с Linux
3.4)
- С Linux 3.4 по Linux 3.11 был
дефект в
определении
cap_usr_time и cap_usr_rdpmc. В
обоих биты
указывали
на одно
место,
поэтому
было
невозможно
узнать что
на самом
деле
установлено:
cap_usr_time или cap_usr_rdpmc.
- Начиная с Linux
3.12, они были
переименованы
в cap_bit0 и
вместо них
вы должны
использовать
поля cap_user_time и
cap_user_rdpmc.
- cap_bit0_is_deprecated
(начиная с Linux
3.12)
- Если
установлен,
то этот бит
показывает,
что ядро
поддерживает
правильно
разделённые
биты cap_user_time и
cap_user_rdpmc.
- Если не
установлен,
то это
означает
используется
старое
ядро, в
котором
cap_usr_time и cap_usr_rdpmc
отражают
один и тот
же бит, и
оба
свойства
нужно
использовать
с
осторожностью.
- cap_user_rdpmc
(начиная с Linux
3.12)
- Если есть
аппаратная
поддержка
чтения
счётчиков
производительности
из
пользовательского
пространства
без
системного
вызова
(инструкция
«rdpmc» в x86), то
для чтения
можно
использовать
следующий
код:
-
u32 seq, time_mult, time_shift, idx, width;
u64 count, enabled, running;
u64 cyc, time_offset;
do {
seq = pc->lock;
barrier();
enabled = pc->time_enabled;
running = pc->time_running;
if (pc->cap_usr_time && enabled != running) {
cyc = rdtsc();
time_offset = pc->time_offset;
time_mult = pc->time_mult;
time_shift = pc->time_shift;
}
idx = pc->index;
count = pc->offset;
if (pc->cap_usr_rdpmc && idx) {
width = pc->pmc_width;
count += rdpmc(idx - 1);
}
barrier();
} while (pc->lock != seq);
- cap_user_time
(начиная с Linux
3.12)
- Этот бит
указывает
на наличие
аппаратного,
неизменяемого,
неостанавливаемого
счётчика
временных
меток (TSC на x86).
- cap_user_time_zero
(начиная с Linux
3.12)
- Указывает
на наличие
time_zero, который
позволяет
отображать
значения
временных
меток в
аппаратные
часы.
- pmc_width
- Если
установлен
cap_usr_rdpmc, то это
поле
предоставляет
ширину (в
битах)
значения,
считываемого
с помощью rdpmc
или
эквивалентной
инструкции.
Может
использоваться
для
расширения
знаком:
-
pmc <<= 64 - pmc_width;
pmc >>= 64 - pmc_width; // сдвиг знака вправо
count += pmc;
- time_shift,
time_mult, time_offset
- Если
установлен
cap_usr_time, то эти
поля можно
использоваться
для
вычисления
разницы
времени,
начиная с
time_enabled (в
наносекундах)
с помощью rdtsc
или
подобной
инструкции.
-
u64 quot, rem;
u64 delta;
quot = cyc >> time_shift;
rem = cyc & (((u64)1 << time_shift) - 1);
delta = time_offset + quot * time_mult +
((rem * time_mult) >> time_shift);
- Где time_offset, time_mult,
time_shift и cyc
читаются в
цикле seqcount,
описанном
выше. Затем
эта
разница
может быть
добавлена
для
включения
и,
возможно,
запуска
(если idx) для
улучшения
масштабирования:
-
enabled += delta;
if (idx)
running += delta;
quot = count / running;
rem = count % running;
count = quot * enabled + (rem * enabled) / running;
- time_zero
(начиная с Linux
3.12)
- Если
установлен
cap_usr_time_zero, то
аппаратные
часы
(счётчик
временных
меток TSC на x86)
могут быть
вычислены
из
значений
time_zero, time_mult и time_shift:
-
time = timestamp - time_zero;
quot = time / time_mult;
rem = time % time_mult;
cyc = (quot << time_shift) + (rem << time_shift) / time_mult;
- И
наоборот:
-
quot = cyc >> time_shift;
rem = cyc & (((u64)1 << time_shift) - 1);
timestamp = time_zero + quot * time_mult +
((rem * time_mult) >> time_shift);
- data_head
- Указывает
на начало
секции
данных.
Значение
непрерывно
увеличивается,
но не
возвращается
в начало.
Перед
доступом к
образцам
его нужно
возвращать
в начало
вручную —
на размер
буфера mmap.
- На
платформах
с SMP после
чтения
значения
data_head из
пользовательского
пространства
нужно
вызвать
функцию rmb().
- data_tail
- Если
отображение
PROT_WRITE, то
значение
data_tail будет
записываться
из
пользовательского
пространства
для
отражения
последних
прочитанных
данных. В
этом
случае
ядро не
перезаписывает
непрочитанные
данные.
- data_offset
(начиная с Linux
4.1)
- Содержит
смещение
расположения
начала
данных
образца perf в
буфере mmap.
- data_size
(начиная с Linux
4.1)
- Содержит
размер
области
образца perf в
буфере mmap.
- aux_head,
aux_tail, aux_offset, aux_size
(начиная с Linux
4.1)
- The AUX region allows mmap(2)-ing a separate sample buffer for
high-bandwidth data streams (separate from the main perf sample buffer).
An example of a high-bandwidth stream is instruction tracing support, as
is found in newer Intel processors.
- Для
задания
области AUX,
сначала
задайте aux_offset
со
смещением
больше чем
data_offset+data_size, а в aux_size
нужно
указать
желаемых
размер
буфера.
Желаемое
смещение и
размер
должны
быть
выровнены
по границе
страницы, и
размер
должен
быть
степенью
двойки.
Затем эти
значения
передаются
в mmap для
отображения
буфера AUX.
Страницы
буфера AUX
учитываются
в
ограничении
ресурса
RLIMIT_MEMLOCK
(смотрите
setrlimit(2)), а также
проходят
допустимость
perf_event_mlock_kb.
- По
умолчанию
буфер AUX
будет
обрезан,
если он не
вмещается
в
доступное
пространство
кольцевого
буфера.
Если буфер
AUX
отображается
только для
чтения, то
он будет
работать в
режиме
кольцевого
буфера, где
старые
данные
перезаписываются
новыми. В
режиме
перезаписи
нельзя
угадать
место
начала
новых
данных, и
задачей
потребителя
становится
отключение
измерения
для
избежания
возможной
состязательности
по данным.
- Указатели
кольцевого
буфера aux_head и
aux_tail
работают и
подчиняются
тем же
правилам,
которые
описаны
выше для data_head
и data_tail.
Далее
приводится
раскладка
страниц
кольцевого
буфера
размером 2^n.
Если
установлен
perf_event_attr.sample_id_all, то
все типы
событий
будут
иметь
выбранные
поля sample_type,
относящиеся
к где/когда
(отличительность)
происходило
событие (TID, TIME, ID,
CPU, STREAM_ID),
описанные
в PERF_RECORD_SAMPLE ниже;
они будут
спрятаны
за perf_event_header и уже
имеющимися
полями, то
есть в
записываться
в конец
полезных
данных. Это
позволяет
читать
новый файл
perf.data старыми
инструментами
perf,
игнорируя
новые
необязательные
поля.
Значения
mmap
начинаются
с
заголовка:
struct perf_event_header {
__u32 type;
__u16 misc;
__u16 size;
};
Далее мы
опишем
поля perf_event_header
более
подробно.
Для
простоты
поля с
короткими
описаниями
показаны
первыми.
- size
- Показывает
размер
записи.
- misc
- В поле misc
содержится
дополнительная
информация
об
образце.
- По этому
значению
можно
определить
режим ЦП,
наложив на
него маску
PERF_RECORD_MISC_CPUMODE_MASK и
одно из
следующих
значений
(заметим,
что это не
битовые
маски,
можно
указывать
только
одно
значение
за раз):
- type
- Значение
type — одно из
представленных
ниже.
Значения в
соответствующей
записи
(следующие
за
заголовком)
зависят от
выбранного
type как
описано.
- PERF_RECORD_MMAP
- События MMAP
записывают
отображения
PROT_EXEC так,
чтобы
можно было
соотнести
IP
пользовательского
пространства
с кодом.
Они имеют
следующую
структуру:
-
struct {
struct perf_event_header header;
u32 pid, tid;
u64 addr;
u64 len;
u64 pgoff;
char filename[];
};
- pid
- идентификатор
процесса.
- tid
- идентификатор
нити.
- addr
- адрес
выделенной
памяти. В len
указывается
длина
выделенной
памяти. В pgoff
указывается
смещение
страницы
выделенной
памяти. В filename
указывается
строка,
описывающая
выделенную
память.
- PERF_RECORD_LOST
- Эта запись
указывает
на потерю
событий.
-
struct {
struct perf_event_header header;
u64 id;
u64 lost;
struct sample_id sample_id;
};
- id
- уникальный
ID события
утерянных
образцов.
- lost
- количество
потерянных
событий.
- PERF_RECORD_COMM
- Эта запись
указывает
на
изменение
имени
процесса.
-
struct {
struct perf_event_header header;
u32 pid;
u32 tid;
char comm[];
struct sample_id sample_id;
};
- pid
- идентификатор
процесса.
- tid
- идентификатор
нити.
- comm
- строка,
содержащая
новое имя
процесса.
- PERF_RECORD_EXIT
- Эта запись
указывает
на событие
выхода
процесса.
-
struct {
struct perf_event_header header;
u32 pid, ppid;
u32 tid, ptid;
u64 time;
struct sample_id sample_id;
};
- PERF_RECORD_THROTTLE,
PERF_RECORD_UNTHROTTLE
- Эта запись
указывает
на событие
включения/выключения
регулировки
(throttle).
-
struct {
struct perf_event_header header;
u64 time;
u64 id;
u64 stream_id;
struct sample_id sample_id;
};
- PERF_RECORD_FORK
- Эта запись
указывает
на событие
порождения
(fork)
процесса.
-
struct {
struct perf_event_header header;
u32 pid, ppid;
u32 tid, ptid;
u64 time;
struct sample_id sample_id;
};
- PERF_RECORD_READ
- Эта запись
указывает
на событие
чтения.
-
struct {
struct perf_event_header header;
u32 pid, tid;
struct read_format values;
struct sample_id sample_id;
};
- PERF_RECORD_SAMPLE
- Эта запись
указывает
на
образец.
-
struct {
struct perf_event_header header;
u64 sample_id; /* if PERF_SAMPLE_IDENTIFIER */
u64 ip; /* if PERF_SAMPLE_IP */
u32 pid, tid; /* if PERF_SAMPLE_TID */
u64 time; /* if PERF_SAMPLE_TIME */
u64 addr; /* if PERF_SAMPLE_ADDR */
u64 id; /* if PERF_SAMPLE_ID */
u64 stream_id; /* if PERF_SAMPLE_STREAM_ID */
u32 cpu, res; /* if PERF_SAMPLE_CPU */
u64 period; /* if PERF_SAMPLE_PERIOD */
struct read_format v;
/* if PERF_SAMPLE_READ */
u64 nr; /* if PERF_SAMPLE_CALLCHAIN */
u64 ips[nr]; /* if PERF_SAMPLE_CALLCHAIN */
u32 size; /* if PERF_SAMPLE_RAW */
char data[size]; /* if PERF_SAMPLE_RAW */
u64 bnr; /* if PERF_SAMPLE_BRANCH_STACK */
struct perf_branch_entry lbr[bnr];
/* if PERF_SAMPLE_BRANCH_STACK */
u64 abi; /* if PERF_SAMPLE_REGS_USER */
u64 regs[weight(mask)];
/* if PERF_SAMPLE_REGS_USER */
u64 size; /* if PERF_SAMPLE_STACK_USER */
char data[size]; /* if PERF_SAMPLE_STACK_USER */
u64 dyn_size; /* if PERF_SAMPLE_STACK_USER &&
size != 0 */
union perf_sample_weight weight;
/* if PERF_SAMPLE_WEIGHT */
/* || PERF_SAMPLE_WEIGHT_STRUCT */
u64 data_src; /* if PERF_SAMPLE_DATA_SRC */
u64 transaction; /* if PERF_SAMPLE_TRANSACTION */
u64 abi; /* if PERF_SAMPLE_REGS_INTR */
u64 regs[weight(mask)];
/* if PERF_SAMPLE_REGS_INTR */
u64 phys_addr; /* if PERF_SAMPLE_PHYS_ADDR */
u64 cgroup; /* if PERF_SAMPLE_CGROUP */
u64 data_page_size;
/* if PERF_SAMPLE_DATA_PAGE_SIZE */
u64 code_page_size;
/* if PERF_SAMPLE_CODE_PAGE_SIZE */
u64 size; /* if PERF_SAMPLE_AUX */
char data[size]; /* if PERF_SAMPLE_AUX */
};
- sample_id
- Если
включён
PERF_SAMPLE_IDENTIFIER, то
добавляется
уникальный
64-битный
идентификатор.
Это дубль
значения id
при PERF_SAMPLE_ID, но
добавляется
в начало
образца,
для
простоты
получения
значения
анализаторами.
- ip
- Если
включён
PERF_SAMPLE_IP, то
добавляется
значение
64-битного
указателя
инструкции.
- pid,
tid
- Если
включён
PERF_SAMPLE_TID, то
добавляется
32-битный
идентификатор
процесс и
32-битный
идентификатор
нити.
- time
- Если
включён
PERF_SAMPLE_TIME, то
добавляется
64-битная
метка
времени.
Она
получается
из local_clock(),
которая
возвращает,
если
возможно,
аппаратную
метку
времени
или
количество
мигов, если
нет.
- addr
- Если
включён
PERF_SAMPLE_ADDR, то
добавляется
64-битный
адрес.
Обычно, это
адрес
точки
трассировки,
останова
или
программного
события; в
противном
случае 0.
- id
- Если
включён
PERF_SAMPLE_ID, то
добавляется
64-битный
уникальный
идентификатор.
Если
события
является
членом
группы
событий, то
возвращается
идентификатор
лидера
группы.
Этот
идентификатор
одинаков
со
значением,
возвращаемым
при PERF_FORMAT_ID.
- stream_id
- Если
включён
PERF_SAMPLE_STREAM_ID, то
добавляется
64-битный
уникальный
идентификатор.
В отличии
от PERF_SAMPLE_ID
возвращается
реальный
идентификатор,
а не лидера
группы.
Этот же
идентификатор
возвращается
при PERF_FORMAT_ID.
- cpu, res
- Если
включён
PERF_SAMPLE_CPU, здесь
хранится
32-битное
значение,
показывающее,
какой
использовался
ЦП, а также
зарезервированное
(неиспользуемое)
32-битное
значение.
- period
- Если
включён
PERF_SAMPLE_PERIOD, то
записывается
64-битное
значение,
отражающее
период
выборки.
- v
- Если
включён
PERF_SAMPLE_READ, то
добавляется
структура
read_format, которая
содержит
значения
для всех
событий
группы
событий.
Добавляемые
значения
зависят от
значения
read_format,
использованного
во время
perf_event_open().
- nr,
ips[nr]
- Если
включён
PERF_SAMPLE_CALLCHAIN, то
добавляется
64-битный
номер,
показывающий
сколько
далее
следует
64-битных
указателей
инструкций.
Это
относится
к текущей
цепочке
вызовов.
- size,
data[size]
- Если
включён
PERF_SAMPLE_RAW, то
добавляется
32-битное
значение,
показывающее
размер
размещённого
далее
массива
8-битных
значений.
Значения
дополняются
нулями до
64-битного.
- Это
неструктурированные
записи с
данными,
скрытыми
программным
интерфейсом.
Не
гарантируется
неизменность
их
структуры
в будущем,
она может
зависеть
от события,
аппаратного
обеспечения
и версии
ядра.
- bnr,
lbr[bnr]
- Если
включён
PERF_SAMPLE_BRANCH_STACK, то
добавляется
64-битное
значение,
показывающее
количество
записей,
следующих
за
структурами
bnr perf_branch_entry,
каждая из
которых
содержит
следующие
поля:
- from
- Источник
инструкции
(может быть
не
ветвление).
- to
- Цель
ветвления.
- mispred
- Цель
ветвления
предсказана
ошибочно.
- predicted
- Цель
ветвления
предсказана.
- in_tx
(начиная с Linux
3.11)
- Ветвление
возникло в
транзакции
транзакционной
памяти.
- abort
(начиная с Linux
3.11)
- Ветвление
возникло в
аварийной
транзакции
транзакционной
памяти.
- cycles
(начиная с Linux
4.3)
- Количество
циклов,
прошедших
с
предыдущего
обновления
стека
ветви.
Элементы
располагаются
от новых к
старым,
таким
образом,
первый
указывает
на самое
новое
ветвление.
Поддержка
mispred, predicted и cycles
необязательна;
если
отсутствует,
то
значения
будут
равны 0.
Тип
сохранённых
ветвлений
указывается
в поле branch_sample_type.
- abi,
regs[weight(mask)]
- Если
включён
PERF_SAMPLE_REGS_USER, то
сохраняются
пользовательские
регистры
ЦП.
- Значением
поля abi
может быть
PERF_SAMPLE_REGS_ABI_NONE, PERF_SAMPLE_REGS_ABI_32
или PERF_SAMPLE_REGS_ABI_64.
- В regs
хранится
массив
регистров
ЦП, которые
были
перечислены
в поле sample_regs_user.
Количество
значений
определяется
количеством
бит,
установленных
в битовой
маске sample_regs_user.
- size,
data[size], dyn_size
- Если
включён
PERF_SAMPLE_STACK_USER, то
сохраняется
пользовательский
стек. Он
может
использоваться
для
генерации
стека
обратных
вызовов.
Значение
size — размер,
запрашиваемый
пользователем
для sample_stack_user или
максимальное
значение
записи.
Значение
data — данные
стека
(неструктурированная
копия
памяти, на
которую
указывает
указатель
стека во
время
взятия
образца).
Значение
dyn_size —
количество
данных,
которые
были
записаны
(может быть
меньше size).
Заметим,
что dyn_size
пропускается,
если size
равно 0.
- weight
- If PERF_SAMPLE_WEIGHT or PERF_SAMPLE_WEIGHT_STRUCT is
enabled, then a 64-bit value provided by the hardware is recorded that
indicates how costly the event was. This allows expensive events to stand
out more clearly in profiles.
- data_src
- Если
включён
PERF_SAMPLE_DATA_SRC, то
сохраняется
64-битное
значение,
состоящее
из
следующих
полей:
- mem_op
- Тип кода
операции,
битовая
комбинация
из
следующих
значений:
- mem_lvl
- Попадание
или промах
по уровням
иерархии
памяти,
побитовая
комбинация
следующего,
сдвинутого
влево на
PERF_MEM_LVL_SHIFT:
- mem_snoop
- Режим
подглядывания
(snoop mode),
побитовая
комбинация
следующего,
сдвинутого
влево на
PERF_MEM_SNOOP_SHIFT:
- mem_lock
- Инструкция
блокировки,
побитовая
комбинация
следующего,
сдвинутого
влево на
PERF_MEM_LOCK_SHIFT:
- mem_dtlb
- Попадание
или промах
доступа к TLB,
побитовая
комбинация
следующего,
сдвинутого
влево на
PERF_MEM_TLB_SHIFT:
- transaction
- Если
установлен
флаг PERF_SAMPLE_TRANSACTION,
то
записывается
64-битное
поле,
описывающее
источники
аварий
транзакционной
памяти.
- Данное
поле
является
побитовым
объединением
следующих
значений:
- Также,
можно
получить
указанный
пользователем
код аварии,
если
сдвинуть 32
бита поля
вправо на
PERF_TXN_ABORT_SHIFT и
наложить
маску PERF_TXN_ABORT_MASK.
- abi,
regs[weight(mask)]
- Если
включён
PERF_SAMPLE_REGS_INTR, то
сохраняются
пользовательские
регистры
ЦП.
- Значением
поля abi
может быть
PERF_SAMPLE_REGS_ABI_NONE, PERF_SAMPLE_REGS_ABI_32
или PERF_SAMPLE_REGS_ABI_64.
- В regs
хранится
массив
регистров
ЦП, которые
были
перечислены
в поле sample_regs_intr.
Количество
значений
определяется
количеством
бит,
установленных
в битовой
маске sample_regs_intr.
- phys_addr
- If the PERF_SAMPLE_PHYS_ADDR flag is set, then the 64-bit physical
address is recorded.
- cgroup
- If the PERF_SAMPLE_CGROUP flag is set, then the 64-bit cgroup ID
(for the perf_event subsystem) is recorded. To get the pathname of the
cgroup, the ID should match to one in a PERF_RECORD_CGROUP.
- data_page_size
- If the PERF_SAMPLE_DATA_PAGE_SIZE flag is set, then the 64-bit page
size value of the data address is recorded.
- code_page_size
- If the PERF_SAMPLE_CODE_PAGE_SIZE flag is set, then the 64-bit page
size value of the ip address is recorded.
- size
- data[size]
- If PERF_SAMPLE_AUX is enabled, a snapshot of the aux buffer is
recorded.
- PERF_RECORD_MMAP2
- This record includes extended information on mmap(2) calls
returning executable mappings. The format is similar to that of the
PERF_RECORD_MMAP record, but includes extra values that allow
uniquely identifying shared mappings. Depending on the
PERF_RECORD_MISC_MMAP_BUILD_ID bit in the header, the extra values
have different layout and meanings.
-
struct {
struct perf_event_header header;
u32 pid;
u32 tid;
u64 addr;
u64 len;
u64 pgoff;
union {
struct {
u32 maj;
u32 min;
u64 ino;
u64 ino_generation;
};
struct { /* if PERF_RECORD_MISC_MMAP_BUILD_ID */
u8 build_id_size;
u8 __reserved_1;
u16 __reserved_2;
u8 build_id[20];
};
};
u32 prot;
u32 flags;
char filename[];
struct sample_id sample_id;
};
- pid
- идентификатор
процесса.
- tid
- идентификатор
нити.
- addr
- адрес
выделенной
памяти.
- len
- длина
выделенной
памяти.
- pgoff
- смещение
на
странице
выделенной
памяти.
- maj
- основной
идентификатор
подлежащего
устройства.
- min
- второстепенный
идентификатор
подлежащего
устройства.
- ino
- номер inode.
- ino_generation
- поколение
inode.
- build_id_size
- is the actual size of build_id field (up to 20).
- build_id
- is a raw data to identify a binary.
- prot
- защитная
информация.
- flags
- информация
о флагах.
- filename
- строка,
описывающая
выделенную
память.
- PERF_RECORD_AUX
(начиная с Linux
4.1)
- Эта запись
сообщает о
доступности
новых
данных в
отдельной
буферной
области AUX.
-
struct {
struct perf_event_header header;
u64 aux_offset;
u64 aux_size;
u64 flags;
struct sample_id sample_id;
};
- aux_offset
- смещение
области AUX mmap,
где
начинаются
новые
данные.
- aux_size
- размер
доступных
данных.
- flags
- описывает
обновление
AUX.
- PERF_RECORD_ITRACE_START
(начиная с Linux
4.1)
- Эта запись
показывает,
что
процесс
начал
событие
трассировки
инструкции,
который
позволяет
инструментам
правильно
соотносить
адреса
инструкций
в буфере AUX с
подходящим
исполняемым
файлом.
-
struct {
struct perf_event_header header;
u32 pid;
u32 tid;
};
- pid
- идентификатор
процесса
нити,
начавшей
трассировку
инструкций.
- tid
- идентификатор
нити для
нити,
начавшей
трассировку
инструкций.
- PERF_RECORD_LOST_SAMPLES
(начиная с Linux
4.2)
- Если
используются
аппаратное
измерение
(такое как Intel
PEBS), то данная
запись
указывает,
что
несколько
образцов
могли
потеряться.
-
struct {
struct perf_event_header header;
u64 lost;
struct sample_id sample_id;
};
- lost
- количество
потенциально
потерянных
образцов.
- PERF_RECORD_SWITCH
(начиная с Linux
4.3)
- Данная
запись
указывает
на
выполнение
переключения
контекста.
Бит PERF_RECORD_MISC_SWITCH_OUT в
поле misc
показывает
направление
переключение
контекста
— из или в
текущий
процесс.
-
struct {
struct perf_event_header header;
struct sample_id sample_id;
};
- PERF_RECORD_SWITCH_CPU_WIDE
(начиная с Linux
4.3)
- Как и у PERF_RECORD_SWITCH
данная
запись
показывает,
что
произошло
переключение
контекста,
но это
случается
только при
измерении
в режиме CPU-wide
и
предоставляет
дополнительную
информацию
о
направлении
переключения
контекста
в/из. Бит
PERF_RECORD_MISC_SWITCH_OUT в
поле misc
показывает
направление
переключения
контекста:
в или из
текущего
процесса.
-
struct {
struct perf_event_header header;
u32 next_prev_pid;
u32 next_prev_tid;
struct sample_id sample_id;
};
- next_prev_pid
- Идентификатор
процесса
предыдущего
(если
переключается
в) или
следующего
(если
переключается
из)
процесса
ЦП.
- next_prev_tid
- Идентификатор
нити
предыдущей
(если
переключается
в) или
следующей
(если
переключается
из) нити ЦП.
- PERF_RECORD_NAMESPACES
(начиная с Linux
4.11)
- This record includes various namespace information of a process.
-
struct {
struct perf_event_header header;
u32 pid;
u32 tid;
u64 nr_namespaces;
struct { u64 dev, inode } [nr_namespaces];
struct sample_id sample_id;
};
- pid
- is the process ID
- tid
- is the thread ID
- nr_namespace
- is the number of namespaces in this record
- Each namespace has dev and inode fields and is recorded in
the fixed position like below:
- PERF_RECORD_KSYMBOL
(начиная с Linux
5.0)
- This record indicates kernel symbol register/unregister events.
-
struct {
struct perf_event_header header;
u64 addr;
u32 len;
u16 ksym_type;
u16 flags;
char name[];
struct sample_id sample_id;
};
- addr
- is the address of the kernel symbol.
- len
- is the length of the kernel symbol.
- ksym_type
- is the type of the kernel symbol. Currently the following types are
available:
- flags
- If the PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER is set, then this event
is for unregistering the kernel symbol.
- PERF_RECORD_BPF_EVENT
(начиная с Linux
5.0)
- This record indicates BPF program is loaded or unloaded.
-
struct {
struct perf_event_header header;
u16 type;
u16 flags;
u32 id;
u8 tag[BPF_TAG_SIZE];
struct sample_id sample_id;
};
- type
- is one of the following values:
- id
- is the ID of the BPF program.
- tag
- is the tag of the BPF program. Currently, BPF_TAG_SIZE is defined
as 8.
- PERF_RECORD_CGROUP
(начиная с Linux
5.7)
- This record indicates a new cgroup is created and activated.
-
struct {
struct perf_event_header header;
u64 id;
char path[];
struct sample_id sample_id;
};
- id
- is the cgroup identifier. This can be also retrieved by
name_to_handle_at(2) on the cgroup path (as a file handle).
- path
- is the path of the cgroup from the root.
- PERF_RECORD_TEXT_POKE
(начиная с Linux
5.8)
- This record indicates a change in the kernel text. This includes addition
and removal of the text and the corresponding length is zero in this
case.
-
struct {
struct perf_event_header header;
u64 addr;
u16 old_len;
u16 new_len;
u8 bytes[];
struct sample_id sample_id;
};
- addr
- is the address of the change
- old_len
- is the old length
- new_len
- is the new length
- bytes
- contains old bytes immediately followed by new bytes.
Обработка
переполнения
Можно
задать
события,
которые
будут
уведомлять
о
прохождении
порога,
указывающие
на
переполнение.
Состояние
переполнения
можно
перехватить,
проследив
за
файловым
дескриптором
событий с
помощью poll(2),
select(2) или epoll(7).
Или же
события
переполнения
можно
перехватить
через
обработчик
сигнала,
включив
ввод-вывод
сигналов о
файловом
дескрипторе;
смотрите
описание
операций
F_SETOWN и F_SETSIG в fcntl(2).
Переполнения
генерируются
только
подсчитывающими
событиями
(значение
sample_period должно
быть
ненулевым).
Существует
два
способа
генерации
уведомлений
о
переполнении.
Первый:
задать
значение
wakeup_events или wakeup_watermark,
которые
будут
срабатывать
после
записи
определённого
количества
образцов
или байт
кольцевой
буфер mmap. В
этом
случае
признаком
служит POLL_IN.
Второй:
использовать
ioctl PERF_EVENT_IOC_REFRESH.
Данный ioctl
добавляется
к счётчику,
который
уменьшается
каждый раз
при
наступлении
события
переполнения.
Если
значение
не равно 0,
то
признаком
служит POLL_IN,
то после
того, как
счётчик
достигнет 0,
признаком
становится
POLL_HUP и
определяющее
событие
отключается.
Актуализация
лидера
группы
событий,
обновляет
всех его
потомков, а
актуализация
с
параметром
0 в
настоящее
время
включает
бесконечную
актуализацию;
такое
поведение
не
поддерживается
и на него
нельзя
полагаться.
Начиная с
Linux 3.18, признак
POLL_HUP
учитывается,
если
отслеживаемое
событие
присоединено
к другому
процессу и
этот
процесс
существует.
Инструкция
rdpmc
Начиная с
Linux 3.4 на x86, вы
можете
использовать
инструкцию
rdpmc для
выполнения
чтения с
низкой
задержкой
без входа в
ядро.
Заметим,
что
использование
rdpmc
необязательно
быстрее
других
способов
чтения
значений
события.
Возможность
использования
этого
можно
определить
по полю cap_usr_rdpmc
страницы mmap;
документацию
по
вычислению
событий
значения
можно
найти в
этом
разделе.
Сначала,
когда
поддержка
rdpmc была
только
включена,
любой
процесс (не
только с
активным
событием perf)
мог
использовать
инструкцию
rdpmc для
доступа к
счётчикам.
Начиная с Linux 4.0
поддержка
rdpmc
разрешена
только,
если
событие в
данный
момент
включено в
контексте
процесса.
Для
возвращению
к старому
поведению
запишите
значение 2 в
/sys/devices/cpu/rdpmc.
Вызовы ioctl
perf_event
К
файловым
дескрипторам
perf_event_open()
допускаются
различные
вызовы ioctl:
- PERF_EVENT_IOC_ENABLE
- Включает
событие
или группу
событий,
указанное
в
аргументе
файлового
дескриптора.
- Если в
аргументе
ioctl
установлен
бит PERF_IOC_FLAG_GROUP, то
включаются
все
события в
группе,
даже если
указанное
событие не
лидер
группы (но
смотрите
ДЕФЕКТЫ).
- PERF_EVENT_IOC_DISABLE
- Отключает
определённый
счётчик
или группу
событий,
указанный
в
аргументе
файлового
дескриптора.
- Включение
или
отключение
лидера
группы
включает
или
выключает
всю группу;
то есть
пока
отключён
лидер
группы, не
считается
ни один из
счётчиков.
Включение
или
выключение
члена
группы (не
лидера)
влияет
только на
этот
счётчик;
выключение
не лидера
останавливает
его
счётчик и
не влияет
на другие
счётчики.
- Если в
аргументе
ioctl
установлен
бит PERF_IOC_FLAG_GROUP, то
выключаются
все
события в
группе,
даже если
указанное
событие не
лидер
группы (но
смотрите
ДЕФЕКТЫ).
- PERF_EVENT_IOC_REFRESH
- Не
унаследованные
счётчики
переполнения
могут
использовать
это для
установки
счётчика
количества
переполнений,
после чего
он
выключается
(значение
задаётся в
аргументе).
Последующие
вызовы
этого ioctl
добавляют
значение
аргумента
в текущий
счётчик.
При каждом
переполнении
будет
возникать
уведомление
о
переполнении
с
установленным
POLL_IN пока
счётчик не
достигнет
0; когда это
произойдёт,
посылается
уведомление
с
установленным
POLL_HUP и
событие
выключается.
Для
значения 0
в
аргументе
поведение
не
определено.
- PERF_EVENT_IOC_RESET
- Сбрасывает
(в ноль)
счётчик
событий,
указанный
в
аргументе
файлового
дескриптора.
Сбрасывается
только
счётчики;
невозможно
обнулить
мультиплексирующее
значение
time_enabled или time_running.
- Если в
аргументе
ioctl
установлен
бит PERF_IOC_FLAG_GROUP, то
сбрасываются
все
события в
группе,
даже если
указанное
событие не
лидер
группы (но
смотрите
ДЕФЕКТЫ).
- PERF_EVENT_IOC_PERIOD
- Обновляет
период
переполнения
события.
- Начиная с Linux
3.7 (на ARM) и Linux 3.14 (на
всех
остальных
архитектурах),
новый
период
начинает
действовать
немедленно.
В старых
ядрах
новый
период не
работает
пока не
возникнет
следующее
переполнение.
- Аргумент
представляет
собой
указатель
на 64-битное
значение,
содержащее
желаемый
новый
период.
- До Linux 2.6.36
данный ioctl
всегда
завершался
с ошибкой
из-за
дефекта в
ядре.
- PERF_EVENT_IOC_SET_OUTPUT
- Указывает
ядру
посылать
уведомляющие
события в
указанный
файловый
дескриптор,
не в
умолчательный.
Все
файловые
дескрипторы
должны
быть на
одном ЦП.
- В
аргументе
указывается
желаемый
файловый
дескриптор
или -1, если
вывод
нужно
игнорировать.
- PERF_EVENT_IOC_SET_FILTER
(начиная с Linux
2.6.33)
- Добавить
фильтр ftrace в
это
событие.
- В
аргументе
указывается
указатель
на
желаемый
фильтр ftrace.
- PERF_EVENT_IOC_ID
(начиная с Linux
3.12)
- Возвращает
значение
идентификатора
события
для
заданного
файлового
дескриптора
события.
- Аргументом
является
указатель
на 64-битное
беззнаковое
целое
число, в
которое
будет
сохранён
результат.
- PERF_EVENT_IOC_SET_BPF
(начиная с Linux
4.1)
- This allows attaching a Berkeley Packet Filter (BPF) program to an
existing kprobe tracepoint event. You need CAP_PERFMON (since Linux
5.8) or CAP_SYS_ADMIN privileges to use this ioctl.
- Аргументом
является
файловый
дескриптор
программы
BPF, который
был создан
ранее
системным
вызовом
bpf(2).
- PERF_EVENT_IOC_PAUSE_OUTPUT
(начиная с Linux
4.7)
- Позволяет
приостанавливать
и
возобновлять
работу
кольцевого
буфера
событий.
Приостановленный
кольцевой
буфер не
останавливает
генерацию
измерений,
а просто
отбрасывает
их.
Отброшенные
измерения
считаются
пропавшими
и
генерируется,
если
возможно,
измерение
PERF_RECORD_LOST. Сигнал
переполнения
по-прежнему
может
возникнуть
из-за
отброшенного
измерения,
даже при
пустом
кольцевом
буфере.
- Аргументом
является
беззнаковое
32-битное
целое.
Ненулевое
значение
приостанавливает
кольцевой
буфер, а
нулевое —
возобновляет
работу
кольцевого
буфера.
- PERF_EVENT_MODIFY_ATTRIBUTES
(начиная с Linux
4.17)
- Позволяет
изменить
существующее
событие
без
накладных
расходов
на
закрытие и
повторное
открытие
нового
события. В
настоящее
время
поддерживается
только для
событий
точек
останова
(breakpoint).
- В
аргументе
содержится
указатель
на
структуру
perf_event_attr с
обновлёнными
данными
события.
- PERF_EVENT_IOC_QUERY_BPF
(начиная с Linux
4.16)
- This allows querying which Berkeley Packet Filter (BPF) programs are
attached to an existing kprobe tracepoint. You can only attach one BPF
program per event, but you can have multiple events attached to a
tracepoint. Querying this value on one tracepoint event returns the ID of
all BPF programs in all events attached to the tracepoint. You need
CAP_PERFMON (since Linux 5.8) or CAP_SYS_ADMIN privileges to
use this ioctl.
- В
аргументе
содержится
указатель
на
структуру
struct perf_event_query_bpf {
__u32 ids_len;
__u32 prog_cnt;
__u32 ids[0];
};
- Значение
поля ids_len
показывает
сколько
идентификаторов
могут
поместиться
в массив ids.
Значение
prog_cnt
заполняется
ядром и
показывает
количество
присоединённых
программ BPF.
Массив ids
заполняется
идентификаторами
каждой
присоединённой
программы
BPF. Если
имеет
больше
программ,
чем
влезает в
массив, то
ядро
вернёт ENOSPC и
ids_len укажет
количество
идентификаторов
программ,
которые
были
успешно
скопированы.
Использование
prctl(2)
Процесс
может
включить
или
выключить
все группы,
в данный
момент,
открытых
событий (с
помощью
операций
prctl(2) PR_TASK_PERF_EVENTS_ENABLE и
PR_TASK_PERF_EVENTS_DISABLE). Это
применимо
только к
событиям
созданным
локально
вызывающим
процессом.
Это не
применимо
к событиям,
созданным
другими
процессами,
присоединёнными
к
вызывающему
процессу,
или к
унаследованным
от
родительского
процесса
событиям.
При этом
включаются
или
выключаются
только
лидеры
групп, а не
члены
групп.
Файлы
настройки
perf_event
Файлы в
/proc/sys/kernel/
- /proc/sys/kernel/perf_event_paranoid
- Файл perf_event_paranoid
можно
использовать
для
ограничения
доступа к
счётчикам
производительности.
- 2
- разрешить
только
измерения
пользовательского
пространства
(по
умолчанию
начиная с Linux
4.6).
- 1
- разрешить
измерения
ядра и
пользовательского
пространства
(по
умолчанию
начиная с Linux
4.6).
- 0
- разрешить
доступ к
данным ЦП,
но не к
структурированным
образцам
точек
трассировки.
- -1
- без
ограничений.
- Наличие
файла perf_event_paranoid
—
официальный
метод
определения
поддержки
ядром perf_event_open().
- /proc/sys/kernel/perf_event_max_sample_rate
- Максимальная
скорость
выборки.
Установка
слишком
большого
значения
может
позволить
пользователям
задать
выборку,
которая
скажется
на
производительности
машины и,
возможно,
заблокирует
машину.
Значение
по
умолчанию
100000 (образов в
секунду).
- /proc/sys/kernel/perf_event_max_stack
- Данный
файл
задаёт
максимальную
глубину
стека
кадров,
выдаваемых
при
генерации
трассировки
вызова.
- /proc/sys/kernel/perf_event_mlock_kb
- Максимальное
количество
страниц,
которое
может
получить
непривилегированный
пользователь
с помощью
mlock(2). По
умолчанию
516 (кБ).
Файлы в
/sys/bus/event_source/devices/
Начиная
с Linux 2.6.34, ядро
поддерживает
использование
нескольких
PMU для
слежения.
Информацию
о
программировании
этих PMU можно
найти
в
/sys/bus/event_source/devices/.
Каждый
подкаталог
соответствует
одному PMU.
- /sys/bus/event_source/devices/*/type
(начиная с Linux
2.6.38)
- Содержит
целое,
которое
можно
использовать
в поле type из
perf_event_attr,
отражает,
что вы
хотите
использовать
этот PMU.
- /sys/bus/event_source/devices/cpu/rdpmc
(начиная с Linux
3.4)
- Если в
файле
значение 1,
то с
помощью
инструкции
rdpmc возможен
прямой
доступ из
пользовательского
пространства
к
регистрам
счётчика
производительности.
Выключить
доступ
можно
посредством
записи 0 в
этот файл.
- В Linux 4.0 это
поведение
изменено,
теперь 1
означает
лишь
доступ к
процессам
с
активными
событиями
perf, а 2
возвращает
старое
поведение
разрешения
доступа
всем.
- /sys/bus/event_source/devices/*/format/
(начиная с Linux
3.4)
- В этом
подкаталоге
содержится
информация
по
зависящим
от
архитектуры
полям,
доступным
для
программирования
различных
полей config
структуры
perf_event_attr.
- The content of each file is the name of the config field, followed by a
colon, followed by a series of integer bit ranges separated by commas. For
example, the file event may contain the value
config1:1,6-10,44 which indicates that event is an attribute that
occupies bits 1,6–10, and 44 of
perf_event_attr::config1.
- /sys/bus/event_source/devices/*/events/
(начиная с Linux
3.4)
- В данном
подкаталоге
содержатся
поля с
предопределёнными
событиями.
Содержимое
— строки,
описывающие
настройки
события в
виде полей
упомянутых
в каталоге
./format/ ранее.
Это не
обязательно
полный
список
всех
событий,
поддерживаемых
PMU, но обычно
это
поднабор
событий,
считаемый
полезным.
- Содержимое
каждого
файла —
список
имён
атрибутов
через
запятую.
Каждая
запись
имеет
необязательное
значение
(десятичное
или
шестнадцатеричное
число).
Если
значение
не указано,
то
предполагается
что это
однобитовое
поле со
значением
1. Пример:
event=0x2,inv,ldlat=3.
- /sys/bus/event_source/devices/*/uevent
- Данный
файл —
стандартное
ядерное
интерфейсное
устройство
для
введения
событий на
лету.
- /sys/bus/event_source/devices/*/cpumask
(начиная с Linux
3.7)
- В файле cpumask
содержится
список
целых
чисел
(через
запятую),
которые
представляют
номер ЦП
для
каждого
сокета
(пакета) на
материнской
плате. Он
необходим
для
настройки
внеядерных
событий
или
событий
северного
моста,
поскольку
эти PMU
представляют
события
всего
сокета.
ДЕФЕКТЫ
Значение
F_SETOWN_EX в fcntl(2)
требуется
для
правильного
получения
сигналов
переполнения
в нитях.
Появилось
в Linux 2.6.32.
До Linux 2.6.33 (как
минимум, на
x86), ядро не
проверяло
возможность
планирования
события
для
совместной
работы до
чтения. Это
же
происходит
на всех
известных
ядрах при
включённом
сторожке NMI.
Чтобы
увидеть,
работает
ли
заданный
набор
событий,
выполните
perf_event_open(), запуск,
затем
выполните
чтения,
зная
наверняка,
что ещё не
можете
получить
корректные
измерения.
До Linux 2.6.34
ограничения
на события
не
соблюдались
ядром. В
этом
случае
некоторые
события
просто
возвращали
«0», если
ядро
планировало
их в
неподходящий
слот
счётчика.
До Linux 2.6.34
существовала
ошибка в
мультиплексировании,
при
котором
могли
вернуться
некорректные
результаты.
Ядра с Linux 2.6.35
по Linux 2.6.39 могли
быстро
упасть,
если
включено
«наследование»
и
запускалось
много
нитей.
До Linux 2.6.35
функция
PERF_FORMAT_GROUP не
работает с
присоединёнными
процессами.
Существует
ошибка в
коде ядра с
Linux 2.6.36 по Linux 3.0, из-за
которой
игнорируется
поле «watermark» и
ядро
работает,
как если бы
было
выбрано wakeup_event,
если
объединение
в нём не
равно
нулю.
С Linux 2.6.31 по Linux 3.4
аргумент ioctl
PERF_IOC_FLAG_GROUP
работает
неправильно
и
постоянно
применяется
к
указанному
событию, а
не ко всем
одноуровневым
событиям в
группе.
С Linux 3.4 по Linux 3.11,
биты mmap cap_usr_rdpmc и
cap_usr_time
отображаются
на одно
расположение.
Использующий
их код
нужно
переписать,
использовав
новые поля
cap_user_rdpmc и cap_user_time.
Всегда
дважды
проверяйте
результаты!
Различные
обобщённые
события
содержат
некорректные
результаты.
Например,
прошедшие
ветви
измеряются
неправильно
на машинах
сAMD до Linux 2.6.35.
ПРИМЕРЫ
Следующий
короткий
пример
показывает
как
подсчитать
количество
инструкций
в вызове
printf(3).
#include <linux/perf_event.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
#include <unistd.h>
static long
perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
int cpu, int group_fd, unsigned long flags)
{
int ret;
ret = syscall(SYS_perf_event_open, hw_event, pid, cpu,
group_fd, flags);
return ret;
}
int
main(void)
{
int fd;
long long count;
struct perf_event_attr pe;
memset(&pe, 0, sizeof(pe));
pe.type = PERF_TYPE_HARDWARE;
pe.size = sizeof(pe);
pe.config = PERF_COUNT_HW_INSTRUCTIONS;
pe.disabled = 1;
pe.exclude_kernel = 1;
pe.exclude_hv = 1;
fd = perf_event_open(&pe, 0, -1, -1, 0);
if (fd == -1) {
fprintf(stderr, "Ошибка открытия лидера %llx\n", pe.config);
exit(EXIT_FAILURE);
}
ioctl(fd, PERF_EVENT_IOC_RESET, 0);
ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
printf("Измерение счётчика количества инструкций для этого printf\n");
ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
read(fd, &count, sizeof(count));
printf("Использовано %lld инструкций\n", count);
close(fd);
}