1. NOM

perf_event_open - Définir la surveillance des performances

2. SYNOPSIS

 
Sélectionnez
#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);

Remarque : il n'existe pas de fonction glibc autour de cet appel système ; consultez NOTES.

3. DESCRIPTION

À partir d'une liste de paramètres, perf_event_open() renvoie un descripteur de fichier, pour une utilisation dans les appels système suivants (read(2), mmap(2), prctl(2), fcntl(2), etc.).

Un appel de perf_event_open() crée un descripteur de fichier qui permet de mesurer les renseignements de performance. Tous les descripteurs de fichier correspondent chacun à un événement mesuré ; ils peuvent être regroupés pour mesurer plusieurs événements simultanément.

Les événements peuvent être activés et désactivés de deux façons : à l'aide de ioctl(2) ou de prctl(2). Quand un événement est désactivé, il ne décompte ni ne génère de dépassement, mais continue vraiment d'exister et maintient sa valeur de décompte.

Les événements existent en deux saveurs : de comptage et d'échantillonnage. Un événement de comptage sert à comptabiliser le nombre total d'événements qui se produisent. En général, les résultats d'un événement de comptage sont recueillis avec un appel read(2). Un événement d'échantillonnage écrit périodiquement les mesures dans un tampon qui peut ensuite être accédé à l'aide de mmap(2).

3.1. Arguments

L'argument pid permet aux événements d'être attachés aux processus de différentes façons. Si pid est 0, les mesures concernent le thread actuel, si pid est strictement supérieur à 0, le processus indiqué par pid est mesuré, et si pid est -1, tous les processus sont comptés. L'argument cpu permet à la mesure d'être spécifique à un processeur. Si cpu est supérieur ou égal à 0, les mesures sont limitées au processeur indiqué ; si cpu est -1, les événements sont mesurés sur tous les processeurs.

Remarquez que la combinaison de pid == -1 et cpu == -1 est impossible.

Un réglage de pid > 0 et cpu == -1 mesure par processus et suit ce processus quelque soit le processeur sur lequel il est programmé. Les événements par processus peuvent être créés par n'importe quel utilisateur.

Un réglage de pid == -1 et cpu >= 0 est par processeur et mesure tous les processus sur le processeur indiqué. Les événements par processeur ont besoin de la capacité CAP_SYS_ADMIN ou d'une valeur /proc/sys/kernel/perf_event_paranoid strictement inférieure à 1.

L'argument group_fd permet aux groupes d'événements d'être créés. Un groupe d'événements a un événement qui est le leader de groupe. Le leader est d'abord créé, avec group_fd = -1. Les autres membres du groupe sont créés par les appels perf_event_open() suivants, avec group_fd défini au descripteur de fichier du leader de groupe (un événement unique créé avec group_fd = -1 est considéré comme formant un groupe d'un seul membre). Un événement de groupe est programmé dans le processeur comme un bloc : il ne sera mis dans le processeur que si tous les événements du groupe peuvent être mis dans le processeur. Cela veut dire que les valeurs des événements de tous les membre peuvent être comparées, ajoutées, divisées (pour obtenir des rapports), etc. ensemble de manière significative, puisqu'elles ont compté les événements pendant les mêmes instructions exécutées.

L'argument flags est constitué d'un OU binaire entre une ou plusieurs des valeurs suivantes.

  • PERF_FLAG_FD_NO_GROUP Cet attribut permet de créer un événement comme faisant partie d'un groupe mais n'ayant aucun leader de groupe. Son utilité est a préciser.
  • PERF_FLAG_FD_OUTPUT
        Cet attribut reroute la sortie d'un événement vers le leader de groupe.
  • PERF_FLAG_PID_CGROUP (depuis Linux 2.6.39)
        Cet attribut active la surveillance par conteneur sur tout le système. Un conteneur est une abstraction qui isole un ensemble de ressources à contrôler plus finement (processeurs, mémoire, etc.) Dans ce mode, l'événement n'est mesuré que si le thread exécuté sur le processeur surveillé appartient au conteneur désigné (cgroup). Le cgroup est identifié en passant un fichier au descripteur de fichier ouvert sur son répertoire dans le système de fichiers cgroupfs. Par exemple, si le cgroup à surveiller est appelé test, alors un descripteur de fichier ouvert sur /dev/cgroup/test (en supposant que cgroupfs est monté sur /dev/cgroup) doit être passé au paramètre pid. La surveillance de cgroup n'est disponible que pour les événements sur tout le système et pourrait donc nécessiter des droits supplémentaires.

La structure perf_event_attr fournit des renseignements de configuration détaillée pour les événements en cours de création.

 
Sélectionnez
struct perf_event_attr {
    __u32     type;         /* Type d'événement */
    __u32     size;         /* Taille de la structure d'attributs */
    __u64     config;       /* Configuration spécifique au type */
    union {
        __u64 sample_period;    /* Période d'échantillonnage */
        __u64 sample_freq;      /* Fréquence d'échantillonnage */
    };
    __u64     sample_type;  /* Indique les valeurs inclues dans
                               l'échantillon */
    __u64     read_format;  /* Indique les valeurs renvoyées en
                               lecture */
    __u64     disabled       : 1,   /* désactivé par défaut */
              inherit        : 1,   /* les fils en hérite */
              pinned         : 1,   /* doit toujours être en PMU */
              exclusive      : 1,   /* ne regrouper qu'en PMU */
              exclude_user   : 1,   /* ne pas compter
                                       l'utilisateur */
              exclude_kernel : 1,   /* ne pas compter le noyau */
              exclude_hv     : 1,   /* ne pas compter
                                       l'hyperviseur */
              exclude_idle   : 1,   /* ne pas compter quand
                                       inactif */
              mmap           : 1,   /* inclure les données mmap */
              comm           : 1,   /* inclure les données comm */
              freq           : 1,   /* utiliser la fréquence, pas
                                       la période */
              inherit_stat   : 1,   /* décomptes par tâche */
              enable_on_exec : 1,   /* prochain exec active */
              task           : 1,   /* tracer la création de fils
                                       et la fin */
              watermark      : 1,   /* wakeup_watermark */
              precise_ip     : 2,   /* contrainte de dérapage */
              mmap_data      : 1,   /* données mmap non exécutées */
              sample_id_all  : 1,   /* tous les événements
                                       sample_type */
              exclude_host   : 1,   /* ne pas compter en hôte */
              exclude_guest  : 1,   /* ne pas compter en client */
              exclude_callchain_kernel : 1,
                                    /* exclure les appels en chaîne
                                       du noyau */
              exclude_callchain_user   : 1,
                                    /* exclure les appels en chaîne
                                       d'utilisateur */
              __reserved_1   : 41;
    union {
        __u32 wakeup_events;    /* réveil tous les n événements */
        __u32 wakeup_watermark; /* octets avant le réveil */
    };
    __u32     bp_type;          /* type de point d'arrêt */
    union {
        __u64 bp_addr;          /* adresse de point d'arrêt */
        __u64 config1;          /* extension de config */
    };
    union {
        __u64 bp_len;           /* taille de point d'arrêt */
        __u64 config2;          /* extension de config1 */
    };
    __u64   branch_sample_type; /* enum perf_branch_sample_type */
    __u64   sample_regs_user;   /* registres utilisateur à renvoyer
                                   dans les échantillons */
    __u32   sample_stack_user;  /* taille de pile à renvoyer dans
                                   les échantillons */
    __u32   __reserved_2;       /* Aligner sur u64 */
};

Les champs de la structure perf_event_attr sont décrits en détail ci-dessous.

  • type
        Ce champ indique le type d'événement dans son ensemble. Il a l'une des valeurs suivantes.
  • PERF_TYPE_HARDWARE
        Cela indique un des événements matériels « généralisés » fournis par le noyau. Consultez la définition du champ config pour plus de précisions.
  • PERF_TYPE_SOFTWARE
        Cela indique un des événements logiciels fournis par le noyau (même si aucune prise en charge matérielle n'est disponible).
  • PERF_TYPE_TRACEPOINT
        Cela indique un point de trace fourni par l'infrastructure de point de trace du noyau.
  • PERF_TYPE_HW_CACHE
        Cela indique un événement de cache matériel. Cela a un encodage particulier décrit dans la définition du champ config.
  • PERF_TYPE_RAW
        Cela indique un événement « brut » spécifique à l'implémentation dans le champ config.
  • PERF_TYPE_BREAKPOINT (depuis Linux 2.6.33)
        Cela indique un point d'arrêt matériel tel que fourni par le processeur. Les points d'arrêt peuvent être des accès en lecture ou écriture sur une adresse ainsi que l'exécution d'une adresse d'instruction.
  • PMU dynamique
        Depuis Linux 2.6.39, perf_event_open() permet de gérer plusieurs PMU. Pour activer cela, une valeur exportée par le noyau peut être utilisée dans le champ type pour indiquer la PMU à utiliser. La valeur à utiliser est trouvable dans le système de fichiers sysfs : un sous-répertoire existe par instance PMU sous /sys/bus/event_source/devices. Le fichier type dans chaque sous-répertoire contient un entier qui peut être utilisé dans le champ type. Par exemple, /sys/bus/event_source/devices/cpu/type contient la valeur de PMU du processeur principal, c'est-à-dire 4 en général.
  • size
        La taille de la structure perf_event_attr pour compatibilités ascendante et descendante. Définissez-la en utilisant sizeof(struct perf_event_attr) pour permettre au noyau de voir la taille de struct au moment de la compilation. Le PERF_ATTR_SIZE_VER0 relatif est défini à 64 ; c'était la taille de la première struct publiée. PERF_ATTR_SIZE_VER1 est 72, correspondant à l'addition des points d'arrêts dans Linux 2.6.33. PERF_ATTR_SIZE_VER2 est 80, correspondant à l'addition d'échantillonnage de branchement dans Linux 3.4. PERF_ATR_SIZE_VER3 est 96, correspondant à l'addition de sample_regs_user et sample_stack_user dans Linux 3.7.
  • config
        Cela indique l'événement voulu, en conjonction avec le champ type. Les champs config1 et config2 sont aussi pris en compte dans les cas où 64 bits ne suffisent pas pour spécifier complètement l'événement. L'encodage de ces champs dépend de l'événement. Le bit le plus significatif (bit 63) de config indique des données de configuration du compteur (brut) spécifique au processeur ; si le bit le plus significatif est indéfini, les 7 bits suivants indiquent un type d'événement et le reste des bits indique l'identifiant de l'événement. Le champ config peut être définit de différentes façons, en fonction de la valeur du champ type précédemment décrit. Suivent les divers réglages possibles pour config, séparés par type. Si type est PERF_TYPE_HARDWARE, un des événements processeur matériel généralisé est mesuré. Ils ne sont pas tous disponibles sur toutes les plateformes. Définissez config à une des valeurs suivantes.
  • PERF_COUNT_HW_CPU_CYCLES
        Nombre total de cycles. Méfiez-vous de ce qui arrive lors de la variation de fréquence du processeur.
  • PERF_COUNT_HW_INSTRUCTIONS
        Instructions retirées. Prenez garde, elles peuvent être affectées par plusieurs problèmes, en particulier les décomptes d'interruptions matérielles.
  • PERF_COUNT_HW_CACHE_REFERENCES
        Accès au cache. En général, cela indique les accès au cache de dernier niveau, mais cela peut dépendre du processeur. Cela pourrait inclure des messages de prefetches et de cohérence ; cela dépend toujours de la conception du processeur.
  • PERF_COUNT_HW_CACHE_MISSES
        Coups ratés du cache. Cela indique généralement les coups ratés du cache de dernier niveau, c'est destiné à être utilisé en conjonction avec l'événement PERF_COUNT_HW_CACHE_REFERENCES pour calculer le taux de coups ratés du cache.
  • PERF_COUNT_HW_BRANCH_INSTRUCTIONS
        Instructions de branchements retirés. Avant Linux 2.6.34, cela utilisait le mauvais événement sur les processeurs AMD.
  • PERF_COUNT_HW_BRANCH_MISSES
        Instructions de branchements mal prédits.
  • PERF_COUNT_HW_BUS_CYCLES
        Cycles de bus, ce qui peut être différent du décompte total de cycles.
  • PERF_COUNT_HW_STALLED_CYCLES_FRONTEND (depuis Linux 3.0)
        Cycles bloqués pendant un problème.
  • PERF_COUNT_HW_STALLED_CYCLES_BACKEND (depuis Linux 3.0)
        Cycles bloqués pendant un retrait.
  • PERF_COUNT_HW_REF_CPU_CYCLES (depuis Linux 3.3)
        Nombre total de cycles ; non affecté par la variation de fréquence du processeur.

Si type est PERF_TYPE_SOFTWARE, les événements logiciels fournis par le noyau sont mesurés. Définissez config à une des valeurs suivantes.

  • PERF_COUNT_SW_CPU_CLOCK
        Cela rend compte de l'horloge du processeur, un temporisateur par processeur à haute résolution.
  • PERF_COUNT_SW_TASK_CLOCK
        Cela rend compte de l'horloge spécifiquement par rapport à la tâche en cours d'exécution.
  • PERF_COUNT_SW_PAGE_FAULTS
        Cela rend compte du nombre d'erreurs de pagination.
  • PERF_COUNT_SW_CONTEXT_SWITCHES
        Cela compte les changements de contexte. Jusqu'à Linux 2.6.34, ils étaient tous signalés comme des événements en espace utilisateur, ils sont maintenant signalés comme ayant lieu dans le noyau.
  • PERF_COUNT_SW_CPU_MIGRATIONS
        Cela rend compte du nombre de fois où le processus a migré vers un nouveau processeur.
  • PERF_COUNT_SW_PAGE_FAULTS_MIN
        Cela compte le nombre d'erreurs mineures de pagination. Elles n'ont pas nécessité d'entrées ou sorties du disque pour les traiter.
  • PERF_COUNT_SW_PAGE_FAULTS_MAJ
        Cela compte le nombre d'erreurs majeures de pagination. Elles ont nécessité des entrées ou sorties de disque pour les traiter.
  • PERF_COUNT_SW_ALIGNMENT_FAULTS (depuis Linux 2.6.33)
        Cela compte le nombre de défauts d'alignement. Ils ont lieu lors d'accès non alignés en mémoire ; le noyau peut les traiter mais cela réduit les performances. Cela n'arrive que sur certaines architectures (jamais sur x86).
  • PERF_COUNT_SW_EMULATION_FAULTS (depuis Linux 2.6.33)     Cela compte le nombre de défauts d'émulation. Le noyau intercepte parfois des instructions non implémentées et les émule pour l'espace utilisateur. Cela peut avoir des conséquences négatives sur les performances. Si type est PERF_TYPE_TRACEPOINT, alors les points de trace du noyau sont mesurés. La valeur à utiliser dans config peut être obtenue depuis tracing/events/*/*/id de debugfs si ftrace est activé dans le noyau. Si type est PERF_TYPE_HW_CACHE, alors un événement de cache du processeur matériel est mesuré. Utilisez l'équation suivante pour calculer la valeur config appropriée.     .nf (perf_hw_cache_id) | (perf_hw_cache_op_id << 8) | (perf_hw_cache_op_result_id << 16)

perf_hw_cache_id est parmi :

  • PERF_COUNT_HW_CACHE_L1D
        pour mesurer le cache de données de niveau 1 ;
  • PERF_COUNT_HW_CACHE_L1I
        pour mesurer le cache d'instructions de niveau 1 ;
  • PERF_COUNT_HW_CACHE_LL
        pour mesurer le cache de dernier niveau ;
  • PERF_COUNT_HW_CACHE_DTLB
        pour mesurer les données TLB ;
  • PERF_COUNT_HW_CACHE_ITLB
        pour mesurer les instructions TLB ;
  • PERF_COUNT_HW_CACHE_BPU
        pour mesurer l'unité de prédiction de branchement ;
  • PERF_COUNT_HW_CACHE_NODE (depuis Linux 3.0)
        pour mesurer les accès à la mémoire locale ;

et perf_hw_cache_op_id est parmi :

  • PERF_COUNT_HW_CACHE_OP_READ
        pour les accès en lecture ;
  • PERF_COUNT_HW_CACHE_OP_WRITE
        pour les accès en écriture ;
  • PERF_COUNT_HW_CACHE_OP_PREFETCH
        pour les accès prefetch ;

et perf_hw_cache_op_result_id est parmi :

  • PERF_COUNT_HW_CACHE_RESULT_ACCESS
        pour mesurer les accès ;
  • PERF_COUNT_HW_CACHE_RESULT_MISS
        pour mesurer les coups ratés. Si type est PERF_TYPE_RAW, alors une valeur config « brute » personnalisée est nécessaire. La plupart des processeurs gèrent les événements qui ne sont pas couverts par les événements « généralisés ». Ceux-ci sont définis par l'implémentation ; consultez le manuel du processeur (par exemple la documentation Intel Volume 3B ou le guide du développeur de BIOS et noyau AMD). La bibliothèque libpfm4 peut être utilisée pour traduire le nom, dans les manuels architecturaux, en valeur hexadécimale brute que perf_event_open() attend dans ce champ. Si type est PERF_TYPE_BREAKPOINT, alors laissez config défini à zéro. Ses paramètres sont définis ailleurs.
  • sample_period, sample_freq
        Un compteur d'« échantillonnage » génère une interruption tous les N événements, où N est donné par sample_period. Un compteur d'échantillonnage a sample_period > 0. Quand une interruption de dépassement arrive, les données demandées sont enregistrées dans le tampon mmap. Le champ sample_type contrôle les données qui sont enregistrées à chaque interruption. sample_freq permet d'utiliser la fréquence au lieu de la période. Dans ce cas, l'attribut freq doit être défini. Le noyau ajustera la période d'échantillonnage pour essayer d'atteindre le taux voulu. Le taux d'ajustement est un tic d'horloge.
  • sample_type
        Les divers bits de ce champ indiquent les valeurs à inclure dans l'échantillon. Elles seront enregistrées dans un tampon circulaire, disponible en espace utilisateur avec mmap(2). L'ordre de sauvegarde des valeurs dans l'échantillon est documenté dans la sous-section Disposition MMAP ci-dessous ; ce n'est pas l'ordre enum perf_event_sample_format.
  • PERF_SAMPLE_IP
        Enregistrement de pointeur d'instruction.
  • PERF_SAMPLE_TID
        Enregistrement des identifiants de processus et de thread.
  • PERF_SAMPLE_TIME
        Enregistrement d'un horodatage.
  • PERF_SAMPLE_ADDR
        Enregistrement d'une adresse, si applicable.
  • PERF_SAMPLE_READ
        Enregistrement des valeurs de décompte de tous les événements d'un groupe, pas seulement du leader de groupe.
  • PERF_SAMPLE_CALLCHAIN
        Enregistrement de l'appel en chaîne (pile de backtrace).
  • PERF_SAMPLE_ID
        Enregistrement d'un identifiant unique pour le leader de groupe d'événement ouvert.
  • PERF_SAMPLE_CPU
        Enregistrement de numéro de processeur.
  • PERF_SAMPLE_PERIOD
        Enregistrement de la période d'échantillonnage actuelle.
  • PERF_SAMPLE_STREAM_ID
        Enregistrement d'un identifiant unique pour l'événement ouvert. Contrairement à PERF_SAMPLE_ID, le véritable identifiant est renvoyé, pas celui du leader de groupe. Cet identifiant est le même que celui renvoyé par PERF_FORMAT_ID.
  • PERF_SAMPLE_RAW
        Enregistrement de données supplémentaires, si applicable. Normalement renvoyées par les événements de point de trace.
  • PERF_SAMPLE_BRANCH_STACK (depuis Linux 3.4)
        Enregistrement de la pile de branchement. Consultez branch_sample_type.
  • PERF_SAMPLE_REGS_USER (depuis Linux 3.7)
        Enregistrement de l'état actuel du registre processeur au niveau utilisateur (les valeurs dans le processus avant d'appeler le noyau).
  • PERF_SAMPLE_STACK_USER (depuis Linux 3.7)
        Enregistrement de la pile au niveau utilisateur, permettant le défilement de la pile.
  • PERF_SAMPLE_WEIGHT (depuis Linux 3.10)
        Enregistrement d'une valeur de poids fournie par le matériel qui exprime le coût de l'événement d'échantillonnage. Cela permet au matériel de mettre en valeur les événements coûteux dans un profil.
  • PERF_SAMPLE_DATA_SRC (depuis Linux 3.10)
        Enregistrement des sources de données : d'où viennent, dans la hiérarchie de mémoire, les données associées à l'instruction d'échantillonnage. Ce n'est disponible que si le matériel sous-jacent prend en charge cette fonctionnalité.
  • read_format
        Ce champ indique le format des données renvoyées par read(2) sur un descripteur de fichier perf_event_open().
  • PERF_FORMAT_TOTAL_TIME_ENABLED
        Ajout du champ time_enabled de 64 bits. Cela peut servir à calculer les totaux estimés si la PMU est sur-utilisée et qu'il y a multiplexage.
  • PERF_FORMAT_TOTAL_TIME_RUNNING
        Ajout du champ time_running de 64 bits. Cela peut servir pour calculer les totaux estimés si la PMU est sur-utilisée et qu'il y a multiplexage.
  • PERF_FORMAT_ID
        Ajout d'une valeur unique de 64 bits qui correspond au groupe de l'événement.
  • PERF_FORMAT_GROUP
        Permettre à toutes les valeurs de décompte d'un groupe d'événement d'être lues avec une lecture.
  • disabled
        Le bit disabled indique si le compteur commence désactivé ou activé. Si désactivé, l'événement peut être activé plus tard par ioctl(2), prctl(2) ou enable_on_exec.
  • inherit
        Le bit inherit indique que le compteur devrait compter les événements des tâches filles comme les tâches indiquées. Cela ne s'applique qu'aux nouvelles filles, pas à celles existantes au moment où le compteur est créé (ni aux nouvelles filles des filles existantes). L'héritage ne fonctionne pas pour certaines combinaisons de read_format, comme PERF_FORMAT_GROUP.
  • pinned
        Le bit pinned indique que le compteur devrait toujours être sur le processeur si c'est possible. Cela ne s'applique qu'aux compteurs matériels et seulement aux leaders de groupe. Si un compteur épinglé ne peut pas être mis dans le processeur (par exemple s'il n'y a pas assez de compteurs matériels ou en cas de confit avec n'importe quel autre événement), alors le compteur arrive en état d'« erreur », où les lectures renvoient une fin de fichier (c'est-à-dire que read(2) renvoie 0) jusqu'à ce que le compteur soit ensuite activé ou désactivé.
  • exclusive
        Le bit exclusive indique que si ce groupe du compteur est sur le processeur, il devrait être le seul groupe utilisant les compteurs du processeur. Cela pourrait permettre à l'avenir de surveiller des programmes pour gérer les fonctionnalités PMU qui doivent fonctionner seules, sans perturber d'autres compteurs matériels.
  • exclude_user
        Si ce bit est défini, le décompte exclut les événements qui arrivent dans l'espace utilisateur.
  • exclude_kernel
        Si ce bit est défini, le décompte exclut les événements qui arrivent dans l'espace du noyau.
  • exclude_hv
        Si ce bit est défini, le décompte exclut les événements qui arrivent dans l'hyperviseur. C'est surtout pour les PMU avec prise en charge intégrée de leur traitement (comme POWER). Une prise en charge supplémentaire est nécessaire pour traiter les mesures d'hyperviseur sur la plupart des machines.
  • exclude_idle
        Si défini, ne pas compter quand le processeur est inactif.
  • mmap
        Le bit mmap active l'enregistrement des événements mmap exécutées.
  • comm
        Le bit comm active le suivi du nom de commande de processus tel que modifié par les appels systèmes exec(2) et prctl(PR_SET_NAME). Malheureusement pour les outils, il n'est pas possible de distinguer un appel système de l'autre.
  • freq
        Si ce bit est activé, alors sample_frequency est utilisé au lieu de sample_period lors du réglage de l'intervalle d'échantillonnage.
  • inherit_stat
        Ce bit active la sauvegarde des décomptes d'événements lors du changement de contexte pour les tâches héritées. Cela n'a de sens que si le champ inherit est défini.
  • enable_on_exec
        Si ce bit est défini, un compteur est automatiquement activé après un appel d'exec(2).
  • task
        Si ce bit est défini, alors les notifications de création de fils et de fin sont inclues au tampon circulaire.
  • watermark
        Si défini, une interruption d'échantillonnage arrive lors du passage de la frontière wakeup_watermark. Sinon les interruptions arrivent après les échantillons wakeup_events.
  • precise_ip (depuis Linux 2.6.35)
        Cela contrôle la quantité de dérapage. Le dérapage est le nombre d'instructions qui s'exécutent entre l'arrivée d'un événement d'intérêt et la possibilité du noyau de s'arrêter pour enregistrer l'événement. Les plus petits dérapages sont meilleurs et permettent d'associer plus précisément les événements correspondant aux instructions, mais le matériel est souvent limité par leur taille. Les valeurs possibles sont les suivantes :
  • 0 -
        SAMPLE_IP peut avoir un dérapage arbitraire ;
  • 1 -
        SAMPLE_IP doit avoir un dérapage constant ;
  • 2 -
        SAMPLE_IP a demandé à avoir dérapage nul ;
  • 3 -
        SAMPLE_IP doit avoir un dérapage nul. Consultez aussi PERF_RECORD_MISC_EXACT_IP.
  • mmap_data (depuis Linux 2.6.36)
        L'équivalent du champ mmap, mais qui active l'inclusion des événements de données mmap dans le tampon circulaire.
  • sample_id_all (depuis Linux 2.6.38)
        Si défini, alors TID, TIME, ID, CPU et STREAM_ID peuvent de plus être inclus dans les non PERF_RECORD_SAMPLE si le sample_type correspondant est sélectionné.
  • exclude_host (depuis Linux 3.2)
        Ne pas mesurer le temps passé dans l'hôte de machine virtuelle.
  • exclude_guest (depuis Linux 3.2)
        Ne pas mesurer le temps passé dans le client de machine virtuelle.
  • exclude_callchain_kernel (depuis Linux 3.7)
        Ne pas inclure les appels en chaîne du noyau.
  • exclude_callchain_user (depuis Linux 3.7)
        Ne pas inclure les appels en chaîne d'utilisateur.
  • wakeup_events, wakeup_watermark
        Cette union indique le nombre d'échantillons (wakeup_events) ou d'octets (wakeup_watermark) qui arrivent avant un signal de dépassement. Celui utilisé est sélectionné par l'attribut watermark. wakeup_events ne compte que les types d'enregistrement PERF_RECORD_SAMPLE. Pour recevoir un signal pour tous les types PERF_RECORD arrivant, définissez wakeup_watermark à 1.
  • bp_type (depuis Linux 2.6.33)
        Cela choisi le type de point d'arrêt. Il est parmi :
  • HW_BREAKPOINT_EMPTY
        pas de point d'arrêt ;
  • HW_BREAKPOINT_R
        compte lors de la lecture de l'emplacement mémoire ;
  • HW_BREAKPOINT_W
        compte lors de l'écriture à l'emplacement mémoire ;
  • HW_BREAKPOINT_RW
        compte lors de la lecture ou l'écriture à l'emplacement mémoire ;
  • HW_BREAKPOINT_X
        compte lors de l'exécution de code à l'emplacement mémoire.

Les valeurs peuvent être combinées à l'aide d'un OU binaire, mais les combinaisons de HW_BREAKPOINT_R ou HW_BREAKPOINT_W avec HW_BREAKPOINT_X ne sont pas permises.

  • bp_addr (depuis Linux 2.6.33)
        bp_addr est l'adresse du point d'arrêt. Pour les points d'arrêt d'exécution, c'est l'adresse mémoire de l'instruction d'intérêt ; pour les points d'arrêt de lecture et écriture, c'est l'adresse mémoire de l'emplacement mémoire d'intérêt.
  • config1 (depuis Linux 2.6.39)
        config1 est utilisé pour définir des événements qui ont besoin d'un registre supplémentaire ou qui sinon ne rentrent pas dans le champ config normal. OFFCORE_EVENTS brut sur Nehalem/Westmere/SandyBridge utilise ce champ en 3.3 et les noyaux suivants.
  • bp_len (depuis Linux 2.6.33)
        bp_len est la taille du point d'arrêt mesuré si type est PERF_TYPE_BREAKPOINT. Les options sont HW_BREAKPOINT_LEN_1, HW_BREAKPOINT_LEN_2, HW_BREAKPOINT_LEN_4 et HW_BREAKPOINT_LEN_8. Pour un point d'arrêt, définissez-le à sizeof(long).
  • config2 (depuis Linux 2.6.39)
         config2 est une extension supplémentaire du champ config1.
  • branch_sample_type (depuis Linux 3.4)
        C'est utilisé avec l'échantillonnage de branchement matériel des processeurs, si disponible. Il peut prendre une des valeurs suivantes.
  • PERF_SAMPLE_BRANCH_USER
        La cible de branchement est dans l'espace utilisateur.
  • PERF_SAMPLE_BRANCH_KERNEL
        La cible de branchement est dans l'espace du noyau.
  • PERF_SAMPLE_BRANCH_HV
        La cible de branchement est dans l'hyperviseur.
  • PERF_SAMPLE_BRANCH_ANY
        N'importe quel type de branchement.
  • PERF_SAMPLE_BRANCH_ANY_CALL
        N'importe quel branchement d'appel.
  • PERF_SAMPLE_BRANCH_ANY_RETURN
        N'importe quel branchement de retour.
  • PERF_SAMPLE_BRANCH_IND_CALL
        Appels indirects.
  • PERF_SAMPLE_BRANCH_PLM_ALL
        Utilisateur, noyau et hyperviseur.
  • sample_regs_user (depuis Linux 3.7)
        Ce masque binaire définit l'ensemble des registres processeur utilisateur à renvoyer dans les échantillons. La disposition du masque de registre est spécifique à l'architecture et définie dans l'en-tête du noyau arch/ARCH/include/uapi/asm/perf_regs.h.
  • sample_stack_user (depuis Linux 3.7)
        Cela définit la taille de la pile utilisateur à renvoyer si PERF_SAMPLE_STACK_USER est indiqué.

3.2. Lecture des résultats

Une fois qu'un descripteur de fichier perf_event_open() a été ouvert, les valeurs de l'événement peuvent être lues depuis le descripteur de fichier. Les valeurs présentes sont indiquées par le champ read_format de la structure attr au moment de l'ouverture. Si le tampon utilisé pour la lecture n'est pas assez grand pour contenir les données, ENOSPC es renvoyé. Voici la disposition des données renvoyées par une lecture.

* 2 Si PERF_FORMAT_GROUP a été indiqué pour permettre de lire tous les événements d'un groupe en une fois :

 
Sélectionnez
struct read_format {
    u64 nr;            /* Le nombre d'événements */
    u64 time_enabled;  /* si PERF_FORMAT_TOTAL_TIME_ENABLED */
    u64 time_running;  /* si PERF_FORMAT_TOTAL_TIME_RUNNING */
    struct
        u64 value;     /* La valeur de l'événement */
        u64 id;        /* si PERF_FORMAT_ID */
    } values[nr];
};

* Si PERF_FORMAT_GROUP n'a pas été indiqué :

 
Sélectionnez
struct read_format {
    u64 value;         /* La valeur de l'événement */
    u64 time_enabled;  /* si PERF_FORMAT_TOTAL_TIME_ENABLED */
    u64 time_running;  /* si PERF_FORMAT_TOTAL_TIME_RUNNING */
    u64 id;            /* si PERF_FORMAT_ID */
};

Les valeurs lues sont les suivantes.

  • nr
        Le nombre d'événements dans le descripteur de fichier. Seulement disponible si PERF_FORMAT_GROUP a été indiqué.
  • time_enabled, time_running
        Temps total pendant lequel l'événement a été activé et exécuté. Normalement ce sont les mêmes. Si plus d'événements sont démarrés que d'emplacements de compteur disponibles sur la PMU, alors il y a multiplexage et les événements ne sont pas exécutés tout le temps. Dans ce cas, les valeurs time_enabled et time running peuvent être utilisées pour estimer une valeur d'ordre de grandeur du décompte.
  • value
        Une valeur positive sur 64 bits contenant le résultat du compteur.
  • id
        Une valeur unique globale pour cet événement en particulier, seulement si PERF_FORMAT_ID a été indiqué dans read_format.

3.3. Disposition MMAP

En utilisant perf_event_open() en mode d'échantillonnage, les événements asynchrones (comme un dépassement de compteur ou un suivi mmap PROT_EXEC) sont journalisés dans un tampon circulaire. Ce tampon circulaire est créé et accédé à l'aide de mmap(2). La taille de mmap devrait être 1+2^n pages, où la première page est une page de métadonnées (struct perf_event_mmap_page) qui contient plusieurs informations comme l'emplacement de la tête du tampon circulaire. Avant le noyau 2.6.39, un bogue oblige à allouer un tampon circulaire mmap lors de l'échantillonnage même s'il n'est pas prévu de l'utiliser. La structure de la première page mmap de métadonnées est la suivante :

 
Sélectionnez
struct perf_event_mmap_page {
    __u32 version;          /* numéro de version de la structure */
    __u32 compat_version;   /* plus petite version compatible */
    __u32 lock;             /* seqlock pour synchronisation */
    __u32 index;            /* identifiant de compteur matériel */
    __s64 offset;           /* ajouter au compteur matériel */
    __u64 time_enabled;     /* temps d'événement actif */
    __u64 time_running;     /* temps d'événement sur processeur */
    union {
        __u64   capabilities;
        __u64   cap_usr_time  : 1,
                cap_usr_rdpmc : 1,
    };
    __u16   pmc_width;
    __u16   time_shift;
    __u32   time_mult;
    __u64   time_offset;
    __u64   __reserved[120];   /* remplissage à 1 k */
    __u64   data_head;         /* tête de la section de données */
    __u64   data_tail;         /* pied écrit en espace utilisateur */
}

Ce qui suit présente les champs de la structure perf_event_mmap_page plus en détail :

  • version
        Numéro de version de cette structure.
  • compat_version
        La plus petite version avec laquelle elle est compatible.
  • lock
        Un seqlock pour la synchronisation.
  • index
        Un identifiant unique de compteur matériel.
  • offset Ajouter cela à la valeur de compteur matériel.
  • time_enabled
        Temps d'activité de l'événement.
  • time_running
        Temps d'exécution de l'événement.
  • cap_usr_time
        Capacité de temps utilisateur.
  • cap_usr_rdpmc
        Si le matériel permet la lecture en espace utilisateur des compteurs de performance sans appel système (c'est l'instruction « rdpmc » sur x86), alors le code suivant peut être utilisé pour faire une lecture :
 
Sélectionnez
u32 seq, time_mult, time_shift, idx, width;
u64 count, enabled, running;
u64 cyc, time_offset;
s64 pmc = 0;
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;
        pmc = rdpmc(idx - 1);
    }
    barrier();
} while (pc->lock != seq);
  • pmc_width
        Si cap_usr_rdpmc, ce champ fournit la taille en bit de la valeur lue en utilisant l'instruction rdpmc ou équivalente. Cela permet d'étendre avec signe le résultat comme ceci :
 
Sélectionnez
pmc <<= 64 - pmc_width;
pmc >>= 64 - pmc_width; // déplacement du signe à droite
count += pmc;
  • time_shift, time_mult, time_offset
         Si cap_usr_time, ces champs peuvent être utilisés pour calculer la différence de temps depuis time_enabled (en nanoseconde) en utilisant rdtsc ou similaire.
 
Sélectionnez
    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 et cyc sont lus dans la boucle seqcount décrite ci-dessus. Cette différence peut être ajoutée à enabled et éventuellement running (si idx), pour améliorer l'échelle :

 
Sélectionnez
    enabled += delta;
    if (idx)
        running += delta;
    quot = count / running;
    rem  = count % running;
    count = quot * enabled + (rem * enabled) / running;
  • data_head
        Cela pointe vers la tête de la section de données. La valeur augmente continuellement, elle n'est pas coupée. Vous devrez couper vous-même la valeur à la taille du tampon mmap avant d'accéder aux échantillons. Sur les palteformes compatibles SMP, après la lecture de la valeur data_head, l'espace utilisateur devrait renvoyer un rmb().
  • data_tail
        Quand l'association est PROT_WRITE, la valeur data_tail devrait être écrite par l'espace utilisateur pour refléter les dernières données lues. Dans ce cas, le noyau n'écrasera pas les données non lues.

Les 2^n pages suivantes du tampon circulaire ont la disposition décrite ci-dessous. Si perf_event_attr.sample_id_all est défini, alors tous les types d'événements auront les champs sample_type sélectionnés relatifs à l'emplacement et à la date (identité) où un événement a eu lieu (TID, TIME, ID, CPU, STREAM_ID) conformément à la description de PERF_RECORD_SAMPLE ci-dessous, il sera stocké juste après le perf_event_header et les champs déjà présents pour les champs existants, c'est-à-dire à la fin de la charge utile. De cette façon, un nouveau perf.data sera pris en charge par les outils de performances plus anciens, avec ces nouveaux champs facultatifs ignorés. Les valeurs mmap commencent par un en-tête :

 
Sélectionnez
struct perf_event_header {
    __u32   type;
    __u16   misc;
    __u16   size;
};

Les champs perf_event_header sont décrits plus précisément ci-dessous.

  • type
        La valeur type est une des suivantes. Les valeurs dans l'enregistrement correspondant (qui suit l'en-tête) dépendent du type sélectionné comme c'est montré.
  • PERF_RECORD_MMAP
        Les événements MMAP enregistrent les associations PROT_EXEC pour pouvoir mettre en corrélation les pointeurs d'instruction en espace utilisateur et le code. Ils ont la structure suivante :
 
Sélectionnez
struct {
    struct perf_event_header header;
    u32    pid, tid;
    u64    addr;
    u64    len;
    u64    pgoff;
    char   filename[];
};
  • PERF_RECORD_LOST
        Cet enregistrement indique quand des événements sont perdus.
 
Sélectionnez
struct {
    struct perf_event_header header;
    u64 id;
    u64 lost;
};
  • id
        est l'identifiant d'événement unique pour les échantillons perdus.
  • lost
        est le nombre d'événements perdus.
  • PERF_RECORD_COMM
        Cet enregistrement indique une modification du nom de processus.
 
Sélectionnez
struct {
    struct perf_event_header header;
    u32 pid, tid;
    char comm[];
};
  • PERF_RECORD_EXIT
        Cet enregistrement indique un événement de fin de processus.
 
Sélectionnez
struct {
    struct perf_event_header header;
    u32 pid, ppid;
    u32 tid, ptid;
    u64 time;
};
  • PERF_RECORD_THROTTLE, PERF_RECORD_UNTHROTTLE
        Cet enregistrement indique un événement de variation de fréquence du processeur.
 
Sélectionnez
struct {
    struct perf_event_header header;
    u64 time;
    u64 id;
    u64 stream_id;
};
  • PERF_RECORD_FORK
        Cet enregistrement indique un événement de création de fils.
 
Sélectionnez
struct {
    struct perf_event_header header;
    u32 pid, ppid;
    u32 tid, ptid;
    u64 time;
};
  • PERF_RECORD_READ
        Cet enregistrement indique un événement de lecture.
 
Sélectionnez
struct {
    struct perf_event_header header;
    u32 pid, tid;
    struct read_format values;
};
  • PERF_RECORD_SAMPLE
        Cet enregistrement indique un échantillon.
 
Sélectionnez
struct {
    struct perf_event_header header;
    u64   ip;         /* si PERF_SAMPLE_IP */
    u32   pid, tid;   /* si PERF_SAMPLE_TID */
    u64   time;       /* si PERF_SAMPLE_TIME */
    u64   addr;       /* si PERF_SAMPLE_ADDR */
    u64   id;         /* si PERF_SAMPLE_ID */
    u64   stream_id;  /* si PERF_SAMPLE_STREAM_ID */
    u32   cpu, res;   /* si PERF_SAMPLE_CPU */
    u64   period;     /* si PERF_SAMPLE_PERIOD */
    struct read_format v; /* si PERF_SAMPLE_READ */
    u64   nr;         /* si PERF_SAMPLE_CALLCHAIN */
    u64   ips[nr];    /* si PERF_SAMPLE_CALLCHAIN */
    u32   size;       /* si PERF_SAMPLE_RAW */
    char  data[size]; /* si PERF_SAMPLE_RAW */
    u64   bnr;        /* si PERF_SAMPLE_BRANCH_STACK */
    struct perf_branch_entry lbr[bnr];
                      /* si PERF_SAMPLE_BRANCH_STACK */
    u64   abi;        /* si PERF_SAMPLE_REGS_USER */
    u64   regs[weight(mask)];
                      /* si PERF_SAMPLE_REGS_USER */
    u64   size;       /* si PERF_SAMPLE_STACK_USER */
    char  data[size]; /* si PERF_SAMPLE_STACK_USER */
    u64   dyn_size;   /* si PERF_SAMPLE_STACK_USER */
    u64   weight;     /* si PERF_SAMPLE_WEIGHT */
    u64   data_src;   /* si PERF_SAMPLE_DATA_SRC */
};
  • ip
        Si PERF_SAMPLE_IP est activé, alors une valeur de pointeur d'instruction sur 64 bits est incluse.
  • pid, tid
        Si PERF_SAMPLE_TID est activé, alors un identifiant de processus sur 32 bits et un identifiant de thread sur 32 bits sont inclus.
  • time
        Si PERF_SAMPLE_TIME est activé, alors un horodatage sur 64 bits est inclus. C'est obtenu à l'aide de local_clock() qui est un horodatage matériel si disponible et la valeur jiffies sinon.
  • addr
        Si PERF_SAMPLE_ADDR est activé, alors une adresse sur 64 bits est incluse. C'est généralement l'adresse d'un point de trace, point d'arrêt ou événement logiciel ; sinon la valeur est 0.
  • id
        Si PERF_SAMPLE_ID est activé, un identifiant unique sur 64 bits est inclus. Si l'événement est membre d'un groupe d'événements, l'identifiant du leader de groupe est renvoyé. Cet identifiant est le même que celui renvoyé par PERF_FORMAT_ID.
  • stream_id
        Si PERF_SAMPLE_STREAM_ID est activé, un identifiant unique sur 64 bits est inclus. Contrairement à PERF_SAMPLE_ID, le véritable identifiant est renvoyé, pas celui du leader de groupe. Cet identifiant est le même que celui renvoyé par PERF_FORMAT_ID.
  • cpu, res
        Si PERF_SAMPLE_CPU est activé, c'est une valeur sur 32 bits indiquant le processeur qui a été utilisé, en supplément d'une valeur réservée (non utilisée) sur 32 bits.
  • period
        Si PERF_SAMPLE_PERIOD est activé, une valeur sur 64 bits indiquant la période d'échantillonnage actuelle est écrite.
  • v
        Si PERF_SAMPLE_READ est activé, une structure de type read_format est incluse avec des valeurs pour tous les événements du groupe d'événements. Les valeurs incluses dépendent de la valeur read_format utilisée au moment de perf_event_open().
  • nr, ips[nr]
        Si PERF_SAMPLE_CALLCHAIN est activé, alors un nombre sur 64 bits est inclus, indiquant le nombre de pointeurs d'instruction sur 64 bits qui suivent. C'est l'appel en chaîne actuel.
  • size, data[size]
        Si PERF_SAMPLE_RAW est activé, alors une valeur sur 32 bits indiquant la taille est incluse, suivie par un tableau de valeurs sur 8 bits de taille size. Les valeurs sont remplies avec des 0 pour avoir un alignement à 64 bits. Ces données brutes d'enregistrement sont opaques du point de vue de l'ABI. L'ABI ne fait pas de promesses sur la stabilité de son contenu, qui pourrait varier en fonction de l'événement, du matériel ou de la version du noyau.
  • bnr, lbr[bnr]
        Si PERF_SAMPLE_BRANCH_STACK est activé, alors une valeur de 64 bits indiquant le nombre d'enregistrements est incluse, suivie des structures bnr perf_branch_entry. Ces structures ont des valeurs d'origine, de destination et d'attributs indiquant les adresses d'origine et de destination des branchements sur la pile d'appel.
  • abi, regs[weight(mask)]
        Si PERF_SAMPLE_REGS_USER est activé, alors les registres processeur utilisateur sont enregistrés. Le champ abi est parmi PERF_SAMPLE_REGS_ABI_NONE, PERF_SAMPLE_REGS_ABI_32 ou PERF_SAMPLE_REGS_ABI_64. Le champ regs est un tableau de registres processeur qui ont été indiqués par le champ attr sample_regs_user. Le nombre de valeurs est le nombre de bits définis dans le masque binaire sample_regs_user.
  • size, data[size], dyn_size
        Si PERF_SAMPLE_STACK_USER est activé, enregistrer la pile utilisateur pour activer le backtrace. size est la taille demandée par l'utilisateur dans stack_user_size ou la taille maximale d'enregistrement. data contient les données de pile. dyn_size est la quantité de données vraiment renvoyée (peut être inférieure à size).
  • weight
        Si PERF_SAMPLE_WEIGHT est activé, une valeur de 64 bit fournie par le matériel est enregistrée pour indiquer le coût de l'événement. Cela permet aux événements coûteux de ressortir plus clairement dans les profils.
  • data_src
        Si PERF_SAMPLE_DATA_SRC est activé, alors une valeur de 64 bits est enregistrée, constituée des champs suivants.
  • mem_op
        type de code opération (opcode), une combinaison bit à bit de PERF_MEM_OP_NA (non disponible), PERF_MEM_OP_LOAD (instruction de chargement), PERF_MEM_OP_STORE (instruction de stockage), PERF_MEM_OP_PFETCH (prefetch) et PERF_MEM_OP_EXEC (code executable).
  • mem_lvl
        niveau de hiérarchie de mémoire atteint ou raté, une combinaison bit à bit de PERF_MEM_LVL_NA (non disponible), PERF_MEM_LVL_HIT (atteint), PERF_MEM_LVL_MISS (raté), PERF_MEM_LVL_L1 (cache de niveau 1), PERF_MEM_LVL_LFB (tampon de capacité), PERF_MEM_LVL_L2 (cache de niveau 2), PERF_MEM_LVL_L3 (cache de niveau 3), PERF_MEM_LVL_LOC_RAM (DRAM local), PERF_MEM_LVL_REM_RAM1 (DRAM distant 1 saut), PERF_MEM_LVL_REM_RAM2 (DRAM distant 2 sauts), PERF_MEM_LVL_REM_CCE1 (cache distant 1 saut), PERF_MEM_LVL_REM_CCE2 (cache distant 2 sauts), PERF_MEM_LVL_IO (mémoire d'entrée et sortie) et PERF_MEM_LVL_UNC (mémoire sans cache).
  • mem_snoop
        mode d'espionnage, une combinaison bit à bit de PERF_MEM_SNOOP_NA (non disponible), PERF_MEM_SNOOP_NONE (pas d'espionnage), PERF_MEM_SNOOP_HIT (espionnage atteint), PERF_MEM_SNOOP_MISS (espionnage raté) et PERF_MEM_SNOOP_HITM (espionnage atteint modifié).
  • mem_lock
        instruction de verrouillage, une combinaison bit à bit de PERF_MEM_LOCK_NA (non disponible) et PERF_MEM_LOCK_LOCKED (transaction verrouillée).
  • mem_dtlb
        accès tlb atteint ou raté, une combinaison bit à bit de PERF_MEM_TLB_NA (non disponible), PERF_MEM_TLB_HIT (atteint), PERF_MEM_TLB_MISS (raté), PERF_MEM_TLB_L1 (TLB de niveau 1), PERF_MEM_TLB_L2 (TLB de niveau 2), PERF_MEM_TLB_WK (parcours matériel), and PERF_MEM_TLB_OS (gestionnaire d'erreur du SE).
  • misc
        Le champ misc contient des renseignements supplémentaires sur l'échantillon. Le mode de processeur peut être déterminé à partir de cette valeur en la masquant avec PERF_RECORD_MISC_CPUMODE_MASK et en recherchant un des suivants (remarquez que ce ne sont pas des masques de bits, un seul peut être défini à la fois).
  • PERF_RECORD_MISC_CPUMODE_UNKNOWN
        Mode de processeur inconnu.
  • PERF_RECORD_MISC_KERNEL
        L'échantillon a eu lieu dans le noyau.
  • PERF_RECORD_MISC_USER
        L'échantillon a eu lieu dans le code utilisateur.
  • PERF_RECORD_MISC_HYPERVISOR
        L'échantillon a eu lieu dans l'hyperviseur.
  • PERF_RECORD_MISC_GUEST_KERNEL
        L'échantillon a eu lieu dans le noyau client.
  • PERF_RECORD_MISC_GUEST_USER
        L'échantillon a eu lieu dans le code utilisateur client. De plus, un des bits suivants peut être défini.
  • PERF_RECORD_MISC_MMAP_DATA
        C'est défini quand l'association n'est pas exécutable ; sinon l'association est exécutable.
  • PERF_RECORD_MISC_EXACT_IP
        Cela indique que le contenu de PERF_SAMPLE_IP pointe vers la véritable instruction qui a déclenché l'événement. Consultez aussi perf_event_attr.precise_ip.
  • PERF_RECORD_MISC_EXT_RESERVED
        Cela indique que des données étendues sont disponibles (actuellement pas utilisées).
  • size
        Cela indique la taille de l'enregistrement.

3.4. Dépassement de signal

Les événements peuvent être définis pour délivrer un signal lorsqu'un seuil est dépassé. Le gestionnaire de signaux est paramétré en utilisant les appels système poll(2), select(2), epoll(2) et fcntl(2). Pour générer des signaux, l'échantillonnage doit être activé (sample_period doit avoir une valeur non nulle). Deux façons permettent de générer des signaux. La première est de paramétrer des valeurs wakeup_events ou wakeup_watermark qui généreront un signal si un certain nombre d'échantillons ou d'octets ont été écrits dans le tampon circulaire mmap. Dans ce cas, un signal de type POLL_IN est envoyé. L'autre façon est en utilisant l'ioctl PERF_EVENT_IOC_REFRESH. Cet ioctl ajoute à un compteur qui décrémente à chaque fois que l'événement dépasse. Quand il est non nul, un signal POLL_IN est envoyé en cas de dépassement, mais une fois que la valeur a atteint 0, un signal de type POLL_HUP est envoyé et l'événement sous-jacent est désactivé. Remarque : sur les nouveaux noyaux (comme remarqué avec le 3.2) un signal est fourni pour chaque dépassement, même si wakeup_events n'est pas défini.

3.5. Instruction rdpmc

À partir de Linux 3.4 sur x86, l'instruction rdpmc permet d'obtenir des lectures à faible latence sans avoir à entrer dans le noyau. Remarquez que l'utilisation de rdpmc n'est pas nécessairement plus rapide que d'autres méthodes pour lire des valeurs d'événement. Cette prise en charge peut être détectée avec le champ cap_usr_rdpmc dans la page mmap ; de la documentation pour calculer les valeurs d'événement est disponible dans cette section.

3.6. Appels ioctl perf_event

Plusieurs ioctls agissent sur les descripteurs de fichier de perf_event_open().

  • PERF_EVENT_IOC_ENABLE
        Activer l'événement individuel ou le groupe d'événements indiqué par l'argument de descripteur de fichier. Si le bit PERF_IOC_FLAG_GROUP est défini dans l'argument ioctl, alors tous les événements d'un groupe sont activés, même si l'événement indiqué n'est pas le leader de groupe.
  • PERF_EVENT_IOC_DISABLE
        Désactiver le compteur individuel ou le groupe d'événements indiqué par l'argument de descripteur de fichier. L'activation ou la désactivation du leader d'un groupe active ou désactive la totalité du groupe. Autrement dit, pendant que le leader de groupe est désactivé, aucun des compteurs du groupe ne compte. L'activation ou la désactivation d'un membre du groupe qui n'est pas le leader arrête ce compteur, mais n'affecte aucun des autres compteurs. Si le bit PERF_IOC_FLAG_GROUP est défini dans l'argument ioctl, alors tous les événements d'un groupe sont désactivés, même si l'événement indiqué n'est pas le leader de groupe.
  • PERF_EVENT_IOC_REFRESH
        Les compteurs de dépassements non hérités peuvent utiliser cela pour activer un compteur pour un nombre de dépassements indiqué par l'argument, après lequel il est désactivé. Les appels suivants de cet ioctl ajoutent la valeur de l'argument au décompte actuel. Un signal avec POLL_IN défini est envoyé à chaque dépassement jusqu'à ce que ce compte atteigne 0 ; quand cela arrive, un signal avec POLL_HUP défini est envoyé et l'événement est désactivé. L'utilisation de 0 comme argument est considéré comme un comportement indéfini.
  • PERF_EVENT_IOC_RESET
        Redéfinir le compte d'événements indiqué par l'argument à zéro. Cela ne réinitialise que les décomptes ; réinitialiser les valeurs de multiplexage time_enabled et time_running est impossible. Si le bit PERF_IOC_FLAG_GROUP est défini dans l'argument ioctl, alors tous les événements d'un groupe sont réinitialisés, même si l'événement indiqué n'est pas le leader de groupe. Si le bit PERF_IOC_FLAG_GROUP n'est pas défini, alors le comportement est quelque peu inattendu : s'il est envoyé à un leader de groupe, seul le leader de groupe est réinitialisé (les fils sont laissés seuls) ; s'il est envoyé à un fils, tous les événements du groupe sont réinitialisés.
  • PERF_EVENT_IOC_PERIOD
        IOC_PERIOD est la commande pour mettre à jour la période ; elle n'est pas mise à jour immédiatement, mais lors de la période suivante. L'argument est un pointeur vers une valeur sur 64 bits contenant la nouvelle période voulue.
  • PERF_EVENT_IOC_SET_OUTPUT
        Cela indique au noyau de signaler les notifications d'événement dans le descripteur de fichier indiqué plutôt que dans celui par défaut. Les descripteurs de fichier doivent tous être sur le même processeur. L'argument indique le descripteur de fichier désiré, ou -1 si la sortie devrait être ignorée.
  • PERF_EVENT_IOC_SET_FILTER (depuis Linux 2.6.33)
        Cela ajoute un filtre ftrace à cet événement. L'argument est un pointeur vers le filtre ftrace voulu.

3.7. Utilisation de prctl

Un processus peut activer ou désactiver tous les groupes d'événements qui lui sont attachés en utilisant les opérations PR_TASK_PERF_EVENTS_ENABLE et PR_TASK_PERF_EVENTS_DISABLE de prctl(2). Cela s'applique à tous les compteurs sur le processus actuel, qu'ils soient créés par ce processus ou par un autre, et n'affecte aucun compteur que ce processus a créé sur d'autres processus. Cela n'active et désactive que les leaders de groupe, aucun autre des membres des groupes.

3.8. Fichiers de configuration relatifs à perf_event

Fichiers de /proc/sys/kernel/

  • /proc/sys/kernel/perf_event_paranoid
         Le fichier perf_event_paranoid peut être défini pour restreindre l'accès aux compteurs de performance : 2 - ne permettre que les mesures en espace utilisateur ; 1 - (par défaut) permettre à la fois les mesures noyau et utilisateur ; 0 - permettre l'accès aux données spécifiques au processeur sauf les échantillons de point de trace brut ; -1 - pas de restriction. L'existence du fichier perf_event_paranoid est la méthode officielle pour déterminer si un noyau gère perf_event_open().
  • /proc/sys/kernel/perf_event_max_sample_rate
         Cela définit le taux d'échantillonnage maximal. Un réglage trop haut peut permettre aux utilisateurs d'échantillonner à un taux ayant un impact sur les performances de la machine et éventuellement verrouiller la machine. La valeur par défaut est 100000 (échantillons par seconde).
  • /proc/sys/kernel/perf_event_mlock_kb
         Le nombre maximal de pages qu'un utilisateur sans droit peut verrouiller avec mlock(2). La valeur par défaut est 516 (ko). Fichiers de /sys/bus/event_source/devices/
        Depuis Linux 2.6.34, le noyau permet d'avoir plusieurs PMU disponibles pour la surveillance. Les informations sur la façon de programmer ces PMU sont disponibles dans /sys/bus/event_source/devices/. Tous les sous-répertoires correspondent à une PMU différente.
  • /sys/bus/event_source/devices/*/type
        Cela contient un entier qui peut être utilisé dans le champ type de perf_event_attr pour indiquer la volonté d'utiliser cette PMU.
  • /sys/bus/event_source/devices/*/rdpmc
        [À documenter]
  • /sys/bus/event_source/devices/*/format/
        Ce sous-répertoire contient des renseignements sur ce à quoi les bits du champ config de perf_event_attr correspondent.
  • /sys/bus/event_source/devices/*/events/
        Ce sous-répertoire contient des fichiers avec des événements prédéfinis. Les contenus sont des chaînes décrivant les réglages d'événements exprimés en termes des champs trouvés dans le répertoire ./format/. Ce ne sont pas nécessairement des listes complètes de tous les champs pris en charge par une PMU, mais généralement un sous-ensemble d'événements jugés utiles ou intéressants.
  • /sys/bus/event_source/devices/*/uevent
        [À documenter]

4. VALEUR RENVOYÉE

perf_event_open() renvoie le nouveau descripteur de fichier, ou -1 en cas d'erreur (auquel cas errno contient le code d'erreur).

5. ERREURS

  • EINVAL
        Renvoyé si l'événement indiqué n'est pas disponible.
  • ENOSPC
        Avant Linux 3.3, s'il manquait de la place pour l'événement, ENOSPC était renvoyé. Linus n'aimait pas cela, et ça a été modifié en EINVAL. ENOSPC est toujours renvoyé en cas de tentative de lecture de résultats dans un tampon trop petit.

6. VERSIONS

perf_event_open() a été introduite dans Linux 2.6.31 mais était appelée perf_counter_open(). Elle a été renommée dans Linux 2.6.32.

7. CONFORMITÉ

Cet appel système perf_event_open() est spécifique à Linux et ne devrait pas être employé dans des programmes destinés à être portables.

8. NOTES

La glibc ne fournit pas de fonction autour de cet appel système ; utilisez syscall(2) pour l'appeler. Consultez l'exemple ci-dessous. Le moyen officiel pour savoir si la prise en charge de perf_event_open() est activée est de vérifier si le fichier /proc/sys/kernel/perf_event_paranoid existe.

9. BOGUES

L'option F_SETOWN_EX de fcntl(2) est nécessaire pour obtenir correctement les signaux de dépassement dans les threads. Cela a été introduit dans Linux 2.6.32. Avant Linux 3.3 (en tout cas pour x86), le noyau ne vérifiait pas si les événements pouvaient être programmés ensemble avant le moment de la lecture. La même chose arrive sur tous les noyaux connus si le watchdog NMI est activé. Cela signifie que pour voir si un ensemble donné d'événements fonctionne, il faut appeler perf_event_open(), démarrer, puis lire avant d'être sûr de pouvoir obtenir des mesures valables. Avant Linux 2.6.34, les contraintes d'événements n'étaient pas renforcées par le noyau. Dans ce cas, certains événements renverraient « 0 » silencieusement si le noyau les avait programmés dans un emplacement de compteur incorrect. Avant Linux 2.6.34, à cause d'un bogue lors du multiplexage, de mauvais résultats pouvaient être renvoyés. Les noyaux de Linux 2.6.35 à Linux 2.6.39 peuvent planter rapidement si inherit est activé et que de nombreux threads sont démarrés. Avant Linux 2.6.35, PERF_FORMAT_GROUP ne fonctionnait pas avec les processus attachés. Dans les plus anciennes versions de Linux 2.6, le rafraîchissement d'un leader de groupe d'événements rafraîchissait tous les frères, et un rafraîchissement avec un paramètre de O activait un rafraîchissement infini. Ce comportement n'est pas géré, et ne devrait pas être utilisé. À cause d'un bogue dans le code du noyau entre Linux 2.6.36 et Linux 3.0, le champ watermark était ignoré et agissait comme si wakeup_event avait été choisi si l'union contenait une valeur non nulle. Vérifiez toujours deux fois les résultats. Plusieurs événements généralisés ont eu de fausses valeurs. Par exemple, les branchements retirés ne mesuraient pas la bonne chose sur les machines AMD jusqu'au noyau 2.6.35.

10. EXEMPLE

Ce qui suit est un court exemple qui mesure le décompte total d'instructions d'un appel à printf(3).

 
Sélectionnez
#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>
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, "Erreur d'ouverture du leader %llx\n", pe.config);
       exit(EXIT_FAILURE);
    }
    ioctl(fd, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
    printf("Mesure du décompte d'instructions pour ce printf\n");
    ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
    read(fd, &count, sizeof(long long));
    printf("%lld instructions utilisées\n", count);
    close(fd);
}

11. VOIR AUSSI

fcntl(2), mmap(2), open(2), prctl(2), read(2)

12. COLOPHON

Cette page fait partie de la publication 3.52 du projet man-pages Linux. Une description du projet et des instructions pour signaler des anomalies peuvent être trouvées à l'adresse http://www.kernel.org/doc/man-pages/.

13. TRADUCTION

Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a <http://po4a.alioth.debian.org/> par l'équipe de traduction francophone au sein du projet perkamon <http://perkamon.alioth.debian.org/>.

Veuillez signaler toute erreur de traduction en écrivant à < >.

Vous pouvez toujours avoir accès à la version anglaise de ce document en utilisant la commande « LC_ALL=C man <section> <page_de_man> ».