对于 perf_event_open,mmap() 比 read() 更快吗?

问题描述 投票:0回答:1
我希望监视应用程序中的许多事件(硬件、软件和硬件缓存)。与大多数进行分析的应用程序一样,性能是关键。在理想的情况下,我将能够使用 mrs 指令直接读取 CPU PMU 事件以进行 CPU 周期计数和其他事件。但由于内核默认禁用从 EL0 访问 PMU,我在应用程序中使用 perf 时陷入困境。

就目前情况而言,我下面的

read_values()

 函数使用 
read() 来读取结果。我一直在寻找加快检索这些性能事件值的方法,并遇到了这个 PMU HW Counter access 文档。

我的问题有两个:

    使用
  1. mmap() 而不是 read() 从 fd 检索值是否可以提高性能?如果是这样,我将如何实现这一目标?
  2. 有没有办法使用mrs coach直接检索PMU寄存器?从上面的
  3. PMU HW Counter access链接,它表明这应该是可能的。尽管我很难找到解释如何执行此操作的示例。
struct read_format { uint64_t nr; /* The number of events */ struct { uint64_t value; /* The value of the event */ uint64_t id; /* if PERF_FORMAT_ID */ } values[nr]; }; int main() { struct perf_event_attr attr1; attr1.type = PERF_TYPE_HARDWARE; attr1.config = PERF_COUNT_HW_CPU_CYCLES; attr1.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID; int main_fd = syscall(__NR_perf_event_open, &attr1, 0, -1, -1, 0); uint64_t id1; ioctl(main_fd, PERF_EVENT_IOC_ID, &id1); ioctl(main_fd, PERF_EVENT_IOC_RESET, 0); ioctl(main_fd, PERF_EVENT_IOC_ENABLE, 0); struct perf_event_attr attr2; attr2.type = PERF_TYPE_HARDWARE; attr2.config = PERF_COUNT_HW_CACHE_REFERENCES; attr2.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID; int fd2 = syscall(__NR_perf_event_open, &attr2, 0, -1, main_fd, 0); uint64_t id2; ioctl(fd2, PERF_EVENT_IOC_ID, &id2); ioctl(fd2, PERF_EVENT_IOC_RESET, 0); ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0); // read_values and log "START" // action // read_values and log "END" return 0; } read_values() { char buffer[4096]; int read_bytes = read(main_fd, &buffer, sizeof(buffer)); if (read_bytes == -1) { return 1; } struct read_format* rf = (struct read_format*) buffer; int values[rf->nr]; for (int i=0; i<rf->nr; i++) { values[i] = rf->values[i].value; } }

read_values()

 read() 调用更改为 
mmap(NULL, sizeof(read_format), PROT_READ, MAP_SHARED, main_fd, 0)
 不起作用。在我的 mmap 调用后读回缓冲区时,由于事件数设置为 0,因此缓冲区未填充。

read_values() { char* buffer = read(main_fd, &buffer, sizeof(buffer)); if (buffer == MAP_FAILED) { return 1; } struct read_format* rf = (struct read_format*) buffer; if (rf->nr == 0) { return 1; } int values[rf->nr]; for (int i=0; i<rf->nr; i++) { values[i] = rf->values[i].value; } }
    
c mmap perf intel-pmu
1个回答
0
投票

mmap()

 无论如何与读入无关。 
mmap()
 允许您映射内存中的文件,但底层软件使用与 
read()
 实际使用的完全相同的机制从磁盘读取文件。

唯一的区别(这使得

mmap()

read()
更好)是它直接将内核缓冲区映射到项目的虚拟内存空间。但这并没有使它变得更快,因为对用于映射的内存的访问仍然需要由内核监视,当您在分配给缓冲区的空间中写入时将缓冲区标记为脏(并且尊重您只写在数据区域,而不是在内务数据中)

这意味着必须对您写入的内存进行一些映射,因此它实际上是写入与文件对应的内核缓冲区中,并且这必须使用与

copy_from

/
copy_to
 中完成的复制类似的机制来完成读。事物经过优化以快速完成,但平均增益不是内存访问相对于磁盘访问的平均增益。

此外,该文件必须可以

mmap()

 这不是一般情况,例如NFS 文件无法映射(或不容易映射),套接字和管道无法映射,设备也无法映射。一般来说,无法 
lseek()
d 的文件将无法被映射。

© www.soinside.com 2019 - 2024. All rights reserved.