PERF_EVENT_OPEN(2)

ИМЯ
perf_event_open - настройка слежения за производительностью

ОБЗОР
#include <linux/perf_event.h>
#include <linux/hw_breakpoint.h>

int perf_event_open(struct perf_event_attr *attr,
                    pid_t pid, int cpu, int group_fd,
                    unsigned long flags);
Замечание: В glibc нет обёрточной функции для данного системного вызова; смотрите ЗАМЕЧАНИЯ.

ОПИСАНИЕ
Получая список параметров, 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
    Это позволяет измерять все процессы/нити на указанном ЦП. Для этого требуется мандат CAP_SYS_ADMIN или значение в /proc/sys/kernel/perf_event_paranoid должно быть меньше 1.

pid == -1 и cpu == -1
    Это некорректные значения и будет возвращена ошибка.

При pid больше нуля право выполнять этот системный вызов определяется проверкой режима доступа ptrace PTRACE_MODE_READ_REALCREDS; смотрите ptrace(2). Аргумент group_fd позволяет создавать группы событий. У группы событий есть одно событие, которое считается лидером. Лидер создаётся самым первым и имеет group_fd = -1. Оставшиеся члены группы создаются последующими вызовами perf_event_open() с group_fd равным файловому дескриптору лидера группы (единственное событие создаётся с group_fd = -1 и считается, что группу имеет только 1 члена). Группа событий планируется для выполнения на одном ЦП как один элемент: он помещается на ЦП только, если все события в группе могут размещаться на ЦП. Это означает, что значения событий-членов могут сравниваться между собой — добавляться, делиться (соотноситься друг с другом) и так далее — следовательно они подсчитывают события для одного набора исполняемых инструкций.

Аргумент 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,   /* по умолчанию выключено */
          inherit        : 1,   /* потомок наследует это */
          pinned         : 1,   /* должно быть всегда на PMU */
          exclusive      : 1,   /* только группа на PMU */
          exclude_user   : 1,   /* не учитывать режим пользователя */
          exclude_kernel : 1,   /* не учитывать режим ядра */
          exclude_hv     : 1,   /* не учитывать режим гипервизора */
          exclude_idle   : 1,   /* не учитывать простой */
          mmap           : 1,   /* включать данные mmap */
          comm           : 1,   /* включать данные comm */
          freq           : 1,   /* использовать частоту вместо
                                       периода */
          inherit_stat   : 1,   /* позадачный учёт */
          enable_on_exec : 1,   /* включать при следующем exec */
          task           : 1,   /* трассировка fork/exit */
          watermark      : 1,   /* wakeup_watermark */
          precise_ip     : 2,   /* ограничение skid */
          mmap_data      : 1,   /* неисполняемые данные mmap */
          sample_id_all  : 1,   /* sample_type всех событий */
          exclude_host   : 1,   /* не учитывать на узле */
          exclude_guest  : 1,   /* не учитывать на госте */
          exclude_callchain_kernel : 1,
                                /* исключать цепочки ядерных
                                   вызовов */
          exclude_callchain_user   : 1,
                                /* исключать цепочки пользовательских
                                   вызовов */
          mmap2          :  1,  /* включать mmap с данными inode */
          comm_exec      :  1,  /* помечать события comm,
                                   произошедшие из-за exec */
          use_clockid    :  1,  /* использовать clockid в полях
                                           времени */
          __reserved_1   : 38;
    union {
        __u32 wakeup_events;    /* пробуждаться каждые n событий */
        __u32 wakeup_watermark; /* байт до пробуждения */
    };
    __u32     bp_type;          /* тип точки останова */
    union {
        __u64 bp_addr;          /* адрес точки останова */
        __u64 config1;          /* расширение config */
    };
    union {
        __u64 bp_len;           /* длина точки останова */
        __u64 config2;          /* расширение config1 */
    };
    __u64 branch_sample_type;   /* enum perf_branch_sample_type */
    __u64 sample_regs_user;     /* пользовательские регистры,
                                   записываемые в замер */
    __u32 sample_stack_user;    /* размер стека, записываемые в
                                   замер */
    __s32 clockid;              /* часы, используемые в полях
                                   времени */
    __u64 sample_regs_intr;     /* регистры, записываемые в замер */
    __u32 aux_watermark;        /* вспомогательные байт перед
                                   пробуждением */
    __u32 __reserved_2;         /* выравнивание до u64 */
};
Описание полей структуры 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.

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 может быть одно из следующих значений:

    PERF_COUNT_HW_CPU_CYCLES
        Общее количество циклов. Опасайтесь того, что происходит во время частотного масштабирования ЦП.

    PERF_COUNT_HW_INSTRUCTIONS
        Запоздалые инструкции (retired instructions). Осторожно, могут влиять различные ситуации, в основном, подсчёт аппаратных прерываний.

    PERF_COUNT_HW_CACHE_REFERENCES
        Доступ к кэшу. Обычно, учитывается доступ к кэшу последнего уровня, но для различных ЦП может быть по-разному. Может включать сообщения о предварительной выборке и связности; опять же, зависит от ЦП.

    PERF_COUNT_HW_CACHE_MISSES
        Промахи кэша. Обычно, отражает промахи кэша последнего уровня; предназначена для использования вместе с событием PERF_COUNT_HW_CACHE_REFERENCES для подсчёта коэффициента промахов кэша.

    PERF_COUNT_HW_BRANCH_INSTRUCTIONS
        Запоздалые инструкции ветвления. До Linux 2.6.35 использовалось неправильное сообщение на процессорах AMD.

    PERF_COUNT_HW_BRANCH_MISSES
        Непредсказанные инструкции ветвления.

    PERF_COUNT_HW_BUS_CYCLES
        Количество циклов шины, которое может отличаться от общего количества циклов.

    PERF_COUNT_HW_STALLED_CYCLES_FRONTEND (начиная с Linux 3.0)
        Блокировано циклов во время проблемы.

    PERF_COUNT_HW_STALLED_CYCLES_BACKEND (начиная с Linux 3.0)
        Блокировано циклов во время запаздывания.

    PERF_COUNT_HW_REF_CPU_CYCLES (начиная с Linux 3.3)
        Общее количество циклов; не подвержено влиянию частотного масштабирования ЦП.

    Если значение 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, должны быть связаны с активным событием. Данное пустое событие позволяет собирать такие записи без необходимости в подсчитывающем событии.
    Если type равно PERF_TYPE_TRACEPOINT, то измеряется точки трассировки ядра. Значение, используемое в config, можно получить из debugfs tracing/events/*/*/id, если ftrace включён в ядре.
    Если type равно PERF_TYPE_HW_CACHE, то измеряется событие кэша аппаратного ЦП. Для вычисления соответствующего значения config используйте следующую формулу:
            (perf_hw_cache_id) | (perf_hw_cache_op_id << 8) |
            (perf_hw_cache_op_result_id << 16)

        где perf_hw_cache_id одно из:

            PERF_COUNT_HW_CACHE_L1D
                для измерения кэша данных 1-го уровня

            PERF_COUNT_HW_CACHE_L1I
                для измерения кэша инструкций 1-го уровня

            PERF_COUNT_HW_CACHE_LL
                для измерения кэша последнего уровня

            PERF_COUNT_HW_CACHE_DTLB
                для измерения TLB данных

            PERF_COUNT_HW_CACHE_ITLB
                для измерения TLB инструкций

            PERF_COUNT_HW_CACHE_BPU
                для измерения модуля предсказания ветвлений

            PERF_COUNT_HW_CACHE_NODE (начиная с Linux 3.1)
                для измерения доступа к локальной памяти

        и perf_hw_cache_op_id одно из

            PERF_COUNT_HW_CACHE_OP_READ
                для доступа на чтение

            PERF_COUNT_HW_CACHE_OP_WRITE
                для доступа на запись

            PERF_COUNT_HW_CACHE_OP_PREFETCH
                для доступа предварительной выборки

        и perf_hw_cache_op_result_id одно из

            PERF_COUNT_HW_CACHE_RESULT_ACCESS
                для измерения доступа

            PERF_COUNT_HW_CACHE_RESULT_MISS
                для измерения промахов
    Если type равно PERF_TYPE_RAW, то требуется пользовательское «неструктурированное» значение config. Большинство ЦП поддерживают события, которые не подпадают под «общие» события. Они определяются реализацией; смотрите руководство на ЦП (например, документацию Intel Volume 3B или AMD BIOS и руководство разработчика ядра). Для трансляции ожидаемых значений в этом поле шестнадцатеричных значений в perf_event_open() из имён справочников по архитектуре можно использовать библиотеку libpfm4. Если type равно PERF_TYPE_BREAKPOINT, то присвойте config значение 0. Его параметры задаются в других местах.

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 больше нуля, то возвращаются значения регистров, захваченных аппаратурой во время измерения запоздалой инструкции.

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
        Позволить все значения счётчиков в группе событий читать за один проход.

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 включается слежение за именем команды процесса, изменяемого системными вызовами exec(2) и prctl(PR_SET_NAME), а также через запись в /proc/self/comm. Если флаг comm_exec также установлен (работает, начиная с Linux 3.16), то можно использовать вспомогательный флаг PERF_RECORD_MISC_COMM_EXEC, чтобы отличить использование exec(2) от остальных.

freq
    Если этот бит установлен, то задания интервала измерения используется sample_frequency, а не sample_period.

inherit_stat
    Этот бит включает сохранение счётчика событий при переключении контекста для наследуемых задач. Это полезно только, если установлен бит inherit.

enable_on_exec
    Если этот бит установлен, то счётчик автоматически включается после вызова exec(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 должен иметь нулевой скат. Смотрите также 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 (т. е. выполняют KVM_RUN ioctl(2)), измеряются только события, возникающие внутри гостевого экземпляра. Имеет смысл только вне гостевых машин; эта настройка не изменяет счётчики, собираемые внутри гостей. В настоящее время работает только на x86.

exclude_guest (начиная с Linux 3.2)
    При проведении измерений, которые включают процессы, запускающие экземпляры VM (т. е. выполняют KVM_RUN ioctl(2)), не измеряются события, возникающие внутри гостевого экземпляра. Имеет смысл только вне гостевых машин; эта настройка не изменяет счётчики, собираемые внутри гостей. В настоящее время работает только на 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, если сообщается о событии переименования, вызванного вызовом exec(2). Это позволяет инструментам различать различные тип переименования процесса.

use_clockid (начиная с Linux 4.1)
    Через clockid позволяет выбрать внутренние часы Linux, используемые для генерации меток времени. Это может облегчить соответствие времён измерений с метками времени, сгенерированными другими инструментами.

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)
    В bp_addr задаётся адрес точки останова. Для точек останова выполнения это адрес памяти интересующей инструкции; для точек останова чтения и записи это адрес памяти интересующего расположения в памяти.

config1 (начиная с Linux 2.6.39)
    Значение config1 используется для задания событий, которым нужен дополнительный регистр или не хватает обычного поля config. Это поле используется в версии ядра 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, то ветви будут включаться в запись ветви. В первой части значения задаётся уровень привилегий, который может быть одним из показанных ниже значений. Если пользователь явно не задал уровень привилегий, то ядро будет использовать уровень привилегий события. Событие и уровни привилегий ветви не совпадают.

    PERF_SAMPLE_BRANCH_USER
        Цель ветвления в пользовательском пространстве

    PERF_SAMPLE_BRANCH_KERNEL
        Цель ветвления в пространстве ядра

    PERF_SAMPLE_BRANCH_HV
        Цель ветвления в гипервизоре.

    PERF_SAMPLE_BRANCH_PLM_ALL
        Подходящее значение состоит из трёх предшествующих значений объединённых OR.

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

    PERF_SAMPLE_BRANCH_ANY
        Любой тип ветвления.

    PERF_SAMPLE_BRANCH_ANY_CALL
        Любой вызов ветвления.

    PERF_SAMPLE_BRANCH_ANY_RETURN
        Любой возврат из ветвления.

    PERF_SAMPLE_BRANCH_IND_CALL
        Косвенные вызовы.

    PERF_SAMPLE_BRANCH_COND (начиная с Linux 3.16)
        Ветвления по условию.

    PERF_SAMPLE_BRANCH_ABORT_TX (начиная с Linux 3.11)
        Аварии транзакционной памяти.

    PERF_SAMPLE_BRANCH_IN_TX (начиная с Linux 3.11)
        Ветвление в транзакции транзакционной памяти.

    PERF_SAMPLE_BRANCH_NO_TX (начиная с Linux 3.11)
        Ветвление не транзакции транзакционной памяти. PERF_SAMPLE_BRANCH_CALL_STACK (начиная с Linux 4.1) Ветвление это часть аппаратно создаваемого стека вызовов. Требует аппаратной поддержки, в настоящее время работает только на Intel x86 Haswell и новее.

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.

  Чтение результатов
После открытия файлового дескриптора с помощью perf_event_open(), значения событий доступны на чтение. События задаются вв поле read_format структуры attr в момент открытия. Если вы попытаетесь выполнить чтение в буфер недостаточного размера, то возвратится ошибка ENOSPC Вот компоновка данных, возвращаемых чтением:

*   Если указан PERF_FORMAT_GROUP для разрешения чтения всех событий в группе за раз:
    struct read_format {
        u64 nr;            /* количество событий */
        u64 time_enabled;  /* если PERF_FORMAT_TOTAL_TIME_ENABLED */
        u64 time_running;  /* если PERF_FORMAT_TOTAL_TIME_RUNNING */
        struct {
            u64 value;     /* значение события */
            u64 id;        /* если PERF_FORMAT_ID */
        } values[nr];
    };

*   Если PERF_FORMAT_GROUP не указан:
    struct read_format {
        u64 value;         /* значение события */
        u64 time_enabled;  /* если PERF_FORMAT_TOTAL_TIME_ENABLED */
        u64 time_running;  /* если PERF_FORMAT_TOTAL_TIME_RUNNING */
        u64 id;            /* если PERF_FORMAT_ID */
    };

Значения полей:

nr  Количество событий в этом файловом дескрипторе. Доступно только, если указан PERF_FORMAT_GROUP.

time_enabled, time_running
    Полное время события с момента включения и с момента выполнения. Обычно они одинаковы. Если было запущено больше событий, чем доступно счётчиков слотов в PMU, то возникает мультиплексирование и события выполняются только часть времени. В этом случае значения time_enabled и time running можно использовать для градации рассчитанного значения в счётчике.

value
    Целое беззнаковое 64-битное значение, содержащее счётчик-результат.

id  Глобально уникальное значение данного события, имеется только, если в read_format указан PERF_FORMAT_ID.

  Разбивка MMAP
При использовании perf_event_open() в режиме измерений, асинхронные события (такие как переполнение счётчика или слежение за PROT_EXEC mmap) протоколируются в кольцевой буфер. Этот кольцевой буфер создаётся и доступен через mmap(2). Размер mmap должен быть 1+2^n страниц, где первая страница — страница метаданных (struct perf_event_mmap_page), в которой содержится различная информация (например, начало кольцевого буфера). До ядра версии 2.6.39, существовал дефект, который требовал от вас выделения кольцевого буфера mmap при измерении, даже если доступ к нему не планировался. Структура первой страницы метаданных 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];   /* дополнение до 1k */
    __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 & ((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 & ((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)
    Область AUX позволяет отобразить отдельный буфер образцов для высокоскоростных потоков данных (отдельный от основного буфера образцов perf). Примером высокоскоростного потока может быть поддержка трассировки инструкций, имеющаяся в новых процессорах Intel. Для задания области 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 и одно из следующих значений (заметим, что это не битовые маски, можно указывать только одно значение за раз):

    PERF_RECORD_MISC_CPUMODE_UNKNOWN
        Неизвестный режим ЦП.

    PERF_RECORD_MISC_KERNEL
        Образец возник в ядре.

    PERF_RECORD_MISC_USER
        Образец возник в пользовательском коде.

    PERF_RECORD_MISC_HYPERVISOR
        Образец возник в гипервизоре.

    PERF_RECORD_MISC_GUEST_KERNEL (начиная с Linux 2.6.35)
        Образец возник в гостевом ядре.

    PERF_RECORD_MISC_GUEST_USER  (начиная с Linux 2.6.35)
        Образец возник в гостевом пользовательском коде.
    Также может быть указан один из следующих бит:

    PERF_RECORD_MISC_MMAP_DATA (начиная с Linux 3.10)
        Устанавливается, когда отображение не выполняемое; в противном случае отображение выполняемое.

    PERF_RECORD_MISC_COMM_EXEC (начиная с Linux 3.16)
        Устанавливается для записи PERF_RECORD_COMM в ядрах новее версии Linux 3.16, если имя процесса изменено системным вызовом exec(2). Является псевдонимом для PERF_RECORD_MISC_MMAP_DATA, хотя как два значения не будут задаваться в одной записи.

    PERF_RECORD_MISC_EXACT_IP
        Показывает, что содержимое PERF_SAMPLE_IP указывает на актуальную инструкцию, из-за которой произошло событие. Смотрите также perf_event_attr.precise_ip.

    PERF_RECORD_MISC_EXT_RESERVED (начиная с Linux 2.6.35)
        Показывает, что доступны расширенные данные (пока не используется).

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;  /* если PERF_SAMPLE_IDENTIFIER */
            u64   ip;         /* если PERF_SAMPLE_IP */
            u32   pid, tid;   /* если PERF_SAMPLE_TID */
            u64   time;       /* если PERF_SAMPLE_TIME */
            u64   addr;       /* если PERF_SAMPLE_ADDR */
            u64   id;         /* если PERF_SAMPLE_ID */
            u64   stream_id;  /* если PERF_SAMPLE_STREAM_ID */
            u32   cpu, res;   /* если PERF_SAMPLE_CPU */
            u64   period;     /* если PERF_SAMPLE_PERIOD */
            struct read_format v; /* если PERF_SAMPLE_READ */
            u64   nr;         /* если PERF_SAMPLE_CALLCHAIN */
            u64   ips[nr];    /* если PERF_SAMPLE_CALLCHAIN */
            u32   size;       /* если PERF_SAMPLE_RAW */
            char  data[size]; /* если PERF_SAMPLE_RAW */
            u64   bnr;        /* если PERF_SAMPLE_BRANCH_STACK */
            struct perf_branch_entry lbr[bnr];
                              /* если PERF_SAMPLE_BRANCH_STACK */
            u64   abi;        /* если PERF_SAMPLE_REGS_USER */
            u64   regs[weight(mask)];
                              /* если PERF_SAMPLE_REGS_USER */
            u64   size;       /* если PERF_SAMPLE_STACK_USER */
            char  data[size]; /* если PERF_SAMPLE_STACK_USER */
            u64   dyn_size;   /* если PERF_SAMPLE_STACK_USER && size != 0 */
            u64   weight;     /* если PERF_SAMPLE_WEIGHT */
            u64   data_src;   /* если PERF_SAMPLE_DATA_SRC */
            u64   transaction;/* если PERF_SAMPLE_TRANSACTION */
            u64   abi;        /* если PERF_SAMPLE_REGS_INTR */
            u64   regs[weight(mask)];
                              /* если PERF_SAMPLE_REGS_INTR */
        };

        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)
                Ветвление возникло в аварийной транзакции транзакционной памяти.

            Элементы располагаются от новых к старым, таким образом, первый указывает на самое новое ветвление. Поддержка mispred и predicted необязательна; если отсутствует, то значения равны 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
            Если включён PERF_SAMPLE_WEIGHT, то добавляется 64-битное аппаратное значение, показывающее стоимость события. Это позволяет выделить в профилях затратные события.

        data_src
            Если включён PERF_SAMPLE_DATA_SRC, то сохраняется 64-битное значение, состоящее из следующих полей:

            mem_op
                Тип кода операции, битовая комбинация из следующих значений:
                PERF_MEM_OP_NA
                    Недоступен
                PERF_MEM_OP_LOAD
                    Инструкция загрузки
                PERF_MEM_OP_STORE
                    Инструкция сохранения
                PERF_MEM_OP_PFETCH
                    Предварительная выборка
                PERF_MEM_OP_EXEC
                    Исполняемый код

            mem_lvl
                Попадание или промах по уровням иерархии памяти, побитовая комбинация следующего, сдвинутого влево на PERF_MEM_LVL_SHIFT:
                PERF_MEM_LVL_NA
                    Недоступен
                PERF_MEM_LVL_HIT
                    Попадание
                PERF_MEM_LVL_MISS
                    Промах
                PERF_MEM_LVL_L1
                    Кэш 1 уровня
                PERF_MEM_LVL_LFB
                    Построчно заполняемый буфер
                PERF_MEM_LVL_L2
                    Кэш 2 уровня
                PERF_MEM_LVL_L3
                    Кэш 3 уровня
                PERF_MEM_LVL_LOC_RAM
                    Локальная оперативная память
                PERF_MEM_LVL_REM_RAM1
                    Удалённая на 1 скачок оперативная память
                PERF_MEM_LVL_REM_RAM2
                    Удалённая на 2 скачка оперативная память
                PERF_MEM_LVL_REM_CCE1
                    Удалённый на 1 скачок кэш
                PERF_MEM_LVL_REM_CCE2
                    Удалённый на 2 скачка кэш
                PERF_MEM_LVL_IO
                    Память ввода-вывода
                PERF_MEM_LVL_UNC
                    Некэшируемая память

            mem_snoop
                Режим подглядывания (snoop mode), побитовая комбинация следующего, сдвинутого влево на PERF_MEM_SNOOP_SHIFT:
                PERF_MEM_SNOOP_NA
                    Недоступен
                PERF_MEM_SNOOP_NONE
                    Нет подглядывания
                PERF_MEM_SNOOP_HIT
                    Срабатывание подглядывания
                PERF_MEM_SNOOP_MISS
                    Промах подглядывания
                PERF_MEM_SNOOP_HITM
                    Срабатывание подглядывания изменено

            mem_lock
                Инструкция блокировки, побитовая комбинация следующего, сдвинутого влево на PERF_MEM_LOCK_SHIFT:
                PERF_MEM_LOCK_NA
                    Недоступен
                PERF_MEM_LOCK_LOCKED
                    Заблокированная транзакция

            mem_dtlb
                Попадание или промах доступа к TLB, побитовая комбинация следующего, сдвинутого влево на PERF_MEM_TLB_SHIFT:
                PERF_MEM_TLB_NA
                    Недоступен
                PERF_MEM_TLB_HIT
                    Попадание
                PERF_MEM_TLB_MISS
                    Промах
                PERF_MEM_TLB_L1
                    1 уровень TLB
                PERF_MEM_TLB_L2
                    2 уровень TLB
                PERF_MEM_TLB_WK
                    Обходчик оборудования
                PERF_MEM_TLB_OS
                    Обработчик ошибок ОС

        transaction
            Если установлен флаг PERF_SAMPLE_TRANSACTION, то записывается 64-битное поле, описывающее источники аварий транзакционной памяти. Данное поле является побитовым объединением следующих значений:

            PERF_TXN_ELISION
                Авария из-за транзакции пропущенного типа (только для ЦП Intel).

            PERF_TXN_TRANSACTION
                Авария из-за общей транзакции.

            PERF_TXN_SYNC
                Синхронная авария (относится к сообщению об инструкции).

            PERF_TXN_ASYNC
                Асинхронная авария (не относится к сообщению об инструкции).

            PERF_TXN_RETRY
                Повторяемая авария (повтор транзакции может привести к успешному выполнению).

            PERF_TXN_CONFLICT
                Авария из-за конфликта памяти между нитями.

            PERF_TXN_CAPACITY_WRITE
                Авария из-за переполнения объёма при записи.

            PERF_TXN_CAPACITY_READ
                Авария из-за переполнения объёма при чтении.

            Также, можно получить указанный пользователем код аварии сдвинув 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.

    PERF_RECORD_MMAP2
        В этой записи добавлена расширенная информация вызовов mmap(2), возвращающих выполняемые отображения. Формат подобен записи PERF_RECORD_MMAP, до добавлены дополнительные значения, позволяющие однозначно определить общие отображения.
        struct {
            struct perf_event_header header;
            u32 pid;
            u32 tid;
            u64 addr;
            u64 len;
            u64 pgoff;
            u32 maj;
            u32 min;
            u64 ino;
            u64 ino_generation;
            u32 prot;
            u32 flags;
            char filename[];
            struct sample_id sample_id;
        };

        pid идентификатор процесса.

        tid идентификатор нити.

        addr
            адрес выделенной памяти.

        len длина выделенной памяти.

        pgoff
            смещение на странице выделенной памяти.

        maj основной идентификатор подлежащего устройства.

        min второстепенный идентификатор подлежащего устройства.

        ino номер inode.

        ino_generation
            поколение inode.

        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_AUX_FLAG_TRUNCATED
                Если установлен, то возвращённые данные были обрезаны до размера доступного буфера.

            PERF_AUX_FLAG_OVERWRITE
                Если установлен, то возвращённые данные перезаписали имеющиеся данные.

    PERF_RECORD_ITRACE_START (начиная с Linux 4.1)
        Эта запись показывает, что процесс начал событие трассировки инструкции, который позволяет инструментам правильно соотносить адреса инструкций в буфере AUX с подходящим исполняемым файлом.
        struct {
            struct perf_event_header header;
            u32 pid;
            u32 tid;
        };

        pid идентификатор процесса нити, начавшей трассировку инструкций.

        tid идентификатор нити для нити, начавшей трассировку инструкций.

  Обработка переполнения
Можно задать события, которые будут уведомлять о прохождении порога, указывающие на переполнение. Условия переполнения можно понять, проследив за файловым дескриптором событий с помощью poll(2), select(2) или epoll(2). Или же можно создать обработчик сигнала SIGIO и с помощью fcntl(2) настроить событие для генерации сигналов SIGIO. Переполнения генерируются только подсчитывающими событиями (значение 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)
    Позволяет присоединить программу Berkeley Packet Filter (BPF) к существующему событию точки трассировки kprobe. Для этого ioctl требуется мандат CAP_SYS_ADMIN. Аргументом является файловый дескриптор программы BPF, который был создан ранее системным вызовом bpf(2).

  Использование prctl
Процесс может включить или выключить все группы событий (с помощью операций 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_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. В каждом файле содержится имя поля config, двоеточие, диапазоны бит через запятую. Например, файл event может содержать значение config1:1,6-10,44, что означает, что событие — атрибут, занимающий биты 1,6-10 и 44 в 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 представляют события всего сокета.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Вызов perf_event_open() возвращает новый дескриптор файла или -1 в случае ошибки (в этом случае errno устанавливается в соответствующее значение).

ОШИБКИ
Ошибки, возвращаемые perf_event_open(), могут различаться на разных процессорных архитектурах и модулях слежения за производительностью.

E2BIG
    Возвращается, если значение perf_event_attr size слишком мало (меньше чем PERF_ATTR_SIZE_VER0), слишком велико (больше размера страницы) или больше чем поддерживает ядро и дополнительные байты не равны нулю. При возврате E2BIG ядро перезаписывает поле size perf_event_attr размером структуры, который ожидался.

EACCES
    Возвращается, когда для запрашиваемого события требуется мандат CAP_SYS_ADMIN (или более разрешительная параноидное perf_event). Распространённые случае, в которых непривилегированный процесс получает эту ошибку: присоединение к процессу, принадлежащему другому пользователю; слежение за всеми процессами на указанном ЦП (т. е., указание в аргументе pid значения -1); не указано exclude_kernel, когда параноидная настройка требует этого.

EBADF
    Возвращается, если файловый дескриптор group_fd некорректен, или если установлен PERF_FLAG_PID_CGROUP и файловый дескриптор cgroup в pid некорректен.

EBUSY (начиная с Linux 4.1)
    Возвращается, если другое событие уже владеет эксклюзивным доступом к PMU.

EFAULT
    Возвращается, если указатель attr указывает на некорректный адрес памяти.

EINVAL
    Возвращается, если указано некорректное событие. Может быть по многим причинам. Неполный список: значение sample_freq больше, чем максимальное настроенное; значение cpu для слежения не существует; значение read_format вне пределов диапазона; значение sample_type вне пределов диапазона; значение flags вне пределов диапазона; указано значение exclusive или pinned и событие не является лидером группы; значения события config вне пределов диапазона или задают зарезервированные биты; выбранное общее событие не поддерживается; не хватает места для добавления события.

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

ENODEV
    Возвращается, когда событие используется свойство, которое не поддерживается текущим ЦП.

ENOENT
    Возвращается, если значение type некорректно. Эта ошибка также возвращается для некоторых неподдерживаемых общих событий.

ENOSPC
    До Linux 3.3, при недостаточности места для события возвращалось значение ENOSPC. В Linux 3.3 она была заменена на EINVAL. Значение ENOSPC всё ещё возвращается, если вы попытаетесь добавить больше событий точек прерывания, чем поддерживается аппаратно.

ENOSYS
    Возвращается, если установлен PERF_SAMPLE_STACK_USER в sample_type и не поддерживается оборудованием.

EOPNOTSUPP
    Возвращается, если требуемое событие запрашивает специального свойства аппаратуры, но оно отсутствует. Возникает при запросе низкоуровневых (low-skid) событий без поддержки, трассировке ветвления без поддержки, выборки, если отсутствует прерывание PMU и стеки ветви для программных событий.

EPERM
    Возвращается на многих (но не всех) архитектурах, если указана неподдерживаемая настройка exclude_hv, exclude_idle, exclude_user или exclude_kernel. Также это может случаться как при EACCES, когда запрашиваемое событие требует мандата CAP_SYS_ADMIN (или более разрешительную параноидную настройку perf_event). Это относится к установке точки останова на адрес ядра и (начиная с Linux 3.13) установке точки трассировки функции ядра.

ESRCH
    Возвращается при попытке присоединения к несуществующему процессу.

ВЕРСИЯ
Системный вызов perf_event_open() появился в Linux 2.6.31, но с именем perf_counter_open(). Он был переименован в Linux 2.6.32.

СООТВЕТСТВИЕ СТАНДАРТАМ
Данный системный вызов perf_event_open() существует только в Linux и не должен использоваться переносимых программах.

ЗАМЕЧАНИЯ
В glibc нет обёртки для данного системного вызова; запускайте его с помощью syscall(2). Смотрите пример ниже. Официальным способом наличия поддержки perf_event_open() является проверка существования файла /proc/sys/kernel/perf_event_paranoid.

ДЕФЕКТЫ
Значение 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 <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <asm/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(__NR_perf_event_open, hw_event, pid, cpu,
                   group_fd, flags);
    return ret;
}
int
main(int argc, char **argv)
{
    struct perf_event_attr pe;
    long long count;
    int fd;
    memset(&pe, 0, sizeof(struct perf_event_attr));
    pe.type = PERF_TYPE_HARDWARE;
    pe.size = sizeof(struct perf_event_attr);
    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(long long));
    printf("Использовано %lld инструкций\n", count);
    close(fd);
}

СМОТРИТЕ ТАКЖЕ
fcntl(2), mmap(2), open(2), prctl(2), read(2)