perf_event_open-如何监视多个事件

perf_event_open-如何监视多个事件,第1张

perf_event_open-如何监视多个事件

有点棘手。

我们照常创建第一个计数器。此外,我们通过

PERF_FORMAT_GROUP
PERF_FORMAT_ID
能够同时使用多个计数器。这个柜台将是我们的小组组长

struct perf_event_attr pea;int fd1, fd2;uint64_t id1, id2;memset(&pea, 0, sizeof(struct perf_event_attr));pea.type = PERF_TYPE_HARDWARE;pea.size = sizeof(struct perf_event_attr);pea.config = PERF_COUNT_HW_CPU_CYCLES;pea.disabled = 1;pea.exclude_kernel = 1;pea.exclude_hv = 1;pea.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;fd1 = syscall(__NR_perf_event_open, &pea, 0, -1, -1, 0);

接下来,我们检索第一个计数器的标识符:

ioctl(fd1, PERF_EVENT_IOC_ID, &id1);

第二个(以及所有其他计数器)以相同的方式创建,只有一个例外:我们将

fd1
值作为组长参数传递:

memset(&pea, 0, sizeof(struct perf_event_attr));pea.type = PERF_TYPE_SOFTWARE;pea.size = sizeof(struct perf_event_attr);pea.config = PERF_COUNT_SW_PAGE_FAULTS;pea.disabled = 1;pea.exclude_kernel = 1;pea.exclude_hv = 1;pea.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;fd2 = syscall(__NR_perf_event_open, &pea, 0, -1, fd1, 0); // <-- hereioctl(fd2, PERF_EVENT_IOC_ID, &id2);

接下来,我们需要声明一个数据结构以一次读取多个计数器。您必须根据传递给的标志声明不同的字段

perf_event_open
。手册页提到了所有可能的字段。在我们的例子中,我们通过
PERF_FORMAT_ID
了添加
id
字段的标志。这将使我们能够区分不同的计数器。

struct read_format {    uint64_t nr;    struct {        uint64_t value;        uint64_t id;    } values[];};

现在我们将标准配置文件称为ioctl:

ioctl(fd1, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP);ioctl(fd1, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP);do_something();ioctl(fd1, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP);

最后,我们从组长文件描述符中读取计数器。这两个计数器都以

read_format
我们声明的单一结构返回:

char buf[4096];struct read_format* rf = (struct read_format*) buf;uint64_t val1, val2;read(fd1, buf, sizeof(buf));for (i = 0; i < rf->nr; i++) {  if (rf->values[i].id == id1) {    val1 = rf->values[i].value;  } else if (rf->values[i].id == id2) {    val2 = rf->values[i].value;  }}printf("cpu cycles: %"PRIu64"n", val1);printf("page faults: %"PRIu64"n", val2);

以下是完整的程序清单:

#define _GNU_SOURCE#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <sys/syscall.h>#include <string.h>#include <sys/ioctl.h>#include <linux/perf_event.h>#include <linux/hw_breakpoint.h>#include <asm/unistd.h>#include <errno.h>#include <stdint.h>#include <inttypes.h>struct read_format {  uint64_t nr;  struct {    uint64_t value;    uint64_t id;  } values[];};void do_something() {  int i;  char* ptr;  ptr = malloc(100*1024*1024);  for (i = 0; i < 100*1024*1024; i++) {    ptr[i] = (char) (i & 0xff); // pagefault  }  free(ptr);}int main(int argc, char* argv[]) {  struct perf_event_attr pea;  int fd1, fd2;  uint64_t id1, id2;  uint64_t val1, val2;  char buf[4096];  struct read_format* rf = (struct read_format*) buf;  int i;  memset(&pea, 0, sizeof(struct perf_event_attr));  pea.type = PERF_TYPE_HARDWARE;  pea.size = sizeof(struct perf_event_attr);  pea.config = PERF_COUNT_HW_CPU_CYCLES;  pea.disabled = 1;  pea.exclude_kernel = 1;  pea.exclude_hv = 1;  pea.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;  fd1 = syscall(__NR_perf_event_open, &pea, 0, -1, -1, 0);  ioctl(fd1, PERF_EVENT_IOC_ID, &id1);  memset(&pea, 0, sizeof(struct perf_event_attr));  pea.type = PERF_TYPE_SOFTWARE;  pea.size = sizeof(struct perf_event_attr);  pea.config = PERF_COUNT_SW_PAGE_FAULTS;  pea.disabled = 1;  pea.exclude_kernel = 1;  pea.exclude_hv = 1;  pea.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;  fd2 = syscall(__NR_perf_event_open, &pea, 0, -1, fd1 , 0);  ioctl(fd2, PERF_EVENT_IOC_ID, &id2);  ioctl(fd1, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP);  ioctl(fd1, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP);  do_something();  ioctl(fd1, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP);  read(fd1, buf, sizeof(buf));  for (i = 0; i < rf->nr; i++) {    if (rf->values[i].id == id1) {      val1 = rf->values[i].value;    } else if (rf->values[i].id == id2) {      val2 = rf->values[i].value;    }  }  printf("cpu cycles: %"PRIu64"n", val1);  printf("page faults: %"PRIu64"n", val2);  return 0;}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4976996.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-13
下一篇 2022-11-14

发表评论

登录后才能评论

评论列表(0条)

保存