0

Here is my code, perf_event_open can not open more than 7 fds

#include <errno.h>
#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,fd1,fd2,fd3,fd4,fd5,fd6,fd7,fd8;

    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, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring instruction count for this printf\n");

    ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
    read(fd, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);

    // ----------------------------------------------------------------------
    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_CPU_CYCLES;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd1 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd1 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd1, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring cpu cycles count for this printf\n");

    ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
    read(fd1, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    // ----------------------------------------------------------------------
    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_CACHE_REFERENCES;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd2 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd2 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd2, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring cache references count for this printf\n");

    ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
    read(fd2, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    // ----------------------------------------------------------------------
    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_CACHE_MISSES;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd3 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd3 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd3, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd3, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring cache misses count for this printf\n");

    ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
    read(fd3, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    // ----------------------------------------------------------------------
    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_BRANCH_INSTRUCTIONS;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd4 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd4 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd4, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd4, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring branch instructions count for this printf\n");

    ioctl(fd4, PERF_EVENT_IOC_DISABLE, 0);
    read(fd4, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    // ----------------------------------------------------------------------
    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_BRANCH_MISSES;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd5 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd5 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd5, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd5, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring branch misses count for this printf\n");

    ioctl(fd5, PERF_EVENT_IOC_DISABLE, 0);
    read(fd5, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    // ----------------------------------------------------------------------
    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_BUS_CYCLES;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd6 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd6 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd6, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd6, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring bus cycles count for this printf\n");

    ioctl(fd6, PERF_EVENT_IOC_DISABLE, 0);
    read(fd6, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    // ----------------------------------------------------------------------
    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_STALLED_CYCLES_FRONTEND;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd7 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd7 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd7, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd7, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring stalled cycles frontend count for this printf\n");

    ioctl(fd7, PERF_EVENT_IOC_DISABLE, 0);
    read(fd7, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    // ----------------------------------------------------------------------
    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_STALLED_CYCLES_BACKEND;
    pe.disabled = 1;
    pe.exclude_kernel = 1;
    pe.exclude_hv = 1;

    fd8 = perf_event_open(&pe, 0, -1, -1, 0);
    if (fd8 == -1) {
       fprintf(stderr, "Error opening leader %llx, errno:%d, reason:%s\n", pe.config, errno, strerror(errno));
       exit(EXIT_FAILURE);
    }

    ioctl(fd8, PERF_EVENT_IOC_RESET, 0);
    ioctl(fd8, PERF_EVENT_IOC_ENABLE, 0);

    printf("Measuring stalled cycles backend count for this printf\n");

    ioctl(fd8, PERF_EVENT_IOC_DISABLE, 0);
    read(fd8, &count, sizeof(long long));

    printf("Used %lld instructions\n", count);
    // ----------------------------------------------------------------------

    close(fd);
    close(fd1);
    close(fd2);
    close(fd3);
    close(fd4);
    close(fd5);
    close(fd6);
    close(fd7);
    close(fd8);
}

here is the output, only the first 7 perf events are opened, the rest of it will failed with errno 2.

Measuring instruction count for this printf 
Used 3857 instructions 
Measuring cpu cycles count for this printf 
Used 1546 instructions
Measuring cache references count for this printf
Used 17 instructions
Measuring cache misses count for this printf
Used 0 instructions
Measuring branch instructions count for this printf
Used 194 instructions
Measuring branch misses count for this printf
Used 12 instructions
Measuring bus cycles count for this printf
Used 34 instructions
Error opening leader 7, errno:2, reason:No such file or directory

I do not find any illustration about this limits in linux man page, would some tell me what's happened, thanks so much. My os version is centos 6.5 .

Jim
  • 1
  • 1

1 Answers1

3

This has nothing to do with the number of open perf events as you can easily find out by simply removing the first 7 perf_event_open calls.

No such file or directory (ENOENT) is not the same as Too many open files (EMFILE). The manpage of perf_event_open explains the return codes:

ENOENT Returned if the type setting is not valid. This error is also returned for some unsupported generic events.

The event is simply not available on your system (with the given kernel). This answer discusses the availability of PERF_COUNT_HW_STALLED_CYCLES_*END events on modern CPUs.

Zulan
  • 21,896
  • 6
  • 49
  • 109
  • 1
    @Jim Glad to help, if the post answers your question, please mark it as accepted by clicking the checkmark left of it. – Zulan Dec 17 '17 at 09:16