0

我在 pi 3b 上使用 raspbian Linux 4.9.78-v7+。

我正在使用 perf 进行一些性能实验。

我正在尝试使用PERF_EVENT_IOC_PERIODperf 来更改流程运行时的时间段。

struct perf_event_attr我在数据结构 中设置了初始采样周期。

我想pe.sample_period在每个样本之后覆盖属性中的这个初始采样周期。

我使用信号来捕获溢出,并使用用户定义的处理程序来更改使用PERF_EVENT_IOC_PERIOD. 但ioctl(fd, PERF_EVENT_IOC_PERIOD, interval);不起作用。相反,我在初始采样期间获取样本。

真的有用吗PERF_EVENT_IOC_PERIOD。?使用PERF_EVENT_IOC_PERIOD.

我的示例代码如下。

#define _GNU_SOURCE 1

#include <asm/unistd.h>
#include <fcntl.h>
#include <linux/perf_event.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

uint64_t old = 200000;
uint64_t prd[] = {200000, 300000, 500000, 800000, 1000000, 1100000, 1500000, 1700000, 2000000, 2200000, 2400000, 2750000, 2900000, 3000000, 3300000, 3400000, 3550000, 3850000, 4000000};

long perf_event_open(struct perf_event_attr* event_attr, pid_t pid, int cpu, int group_fd, unsigned long flags)
{
    return syscall(__NR_perf_event_open, event_attr, pid, cpu, group_fd, flags);
}

static void perf_event_handler(int signum, siginfo_t* info, void* ucontext) {
   if(info->si_code != POLL_HUP) {
      uint64_t newp = prd[++idx]; 
      uint64_t interval = old - newp;
      old = newp;
      ioctl(info->si_fd, PERF_EVENT_IOC_PERIOD, interval);  
    }

}

int main(int argc, char** argv)
{
    // Configure signal handler
    struct sigaction sa;
    memset(&sa, 0, sizeof(struct sigaction));
    sa.sa_sigaction = perf_event_handler;
    sa.sa_flags = SA_SIGINFO;

// Setup signal handler
if (sigaction(SIGIO, &sa, NULL) < 0) {
    fprintf(stderr,"Error setting up signal handler\n");
    perror("sigaction");
    exit(EXIT_FAILURE);
}

// Configure perf_event_attr struct
struct perf_event_attr pe;
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;     // Count retired hardware instructions
pe.disabled = 1;        // Event is initially disabled
pe.sample_type = PERF_SAMPLE_IP;
pe.sample_period = 200000;
pe.exclude_kernel = 1;      // excluding events that happen in the kernel-space
pe.exclude_hv = 1;          // excluding events that happen in the hypervisor

pid_t pid = 0;  // measure the current process/thread
int cpu = -1;   // measure on any cpu
int group_fd = -1;
unsigned long flags = 0;

int fd = perf_event_open(&pe, pid, cpu, group_fd, flags);
if (fd == -1) {
    fprintf(stderr, "Error opening leader %llx\n", pe.config);
    perror("perf_event_open");
    exit(EXIT_FAILURE);
}
  //allocate memory for recording perf samples  
pages = mmap(NULL, 4096*8192, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 

// Setup event handler for overflow signals
fcntl(fd, F_SETFL, O_NONBLOCK|O_ASYNC);
fcntl(fd, F_SETSIG, SIGIO);
fcntl(fd, F_SETOWN, getpid());

ioctl(fd, PERF_EVENT_IOC_RESET, 0);     // Reset event counter to 0
ioctl(fd, PERF_EVENT_IOC_REFRESH, 19);   // 

// Start monitoring

    long loopCount = 1000000;
    long c = 0;
    long i = 0;

    // Some sample payload.
    for(i = 0; i < loopCount; i++) {
        c += 1;
    }

// End monitoring

    ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);   // Disable event

    parse_samples(pages); //parse recorded samples
    munmap(pages, 4096*8192); //free allocated memory


    close(fd);
}

代码基于 此处提供的示例

4

2 回答 2

2

好的..看起来 ioctl 函数调用正在返回 EINVAL PERF_EVENT_IOC_PERIOD。请参阅 截至 2020 年 1 月 30 日的 PERF_EVENT_IOC_PERIOD 上的 ioctl 调用失败。

于 2020-02-12T17:32:03.903 回答
0

ioctl期望一个指向样本周期的指针(尽管显然只读取它):

ioctl(fd, PERF_EVENT_IOC_PERIOD, &interval);
于 2020-05-05T01:33:29.637 回答