就目前情况而言,我下面的
read_values()
函数使用read() 来读取结果。我一直在寻找加快检索这些性能事件值的方法,并遇到了这个 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;
}
}
mmap()
无论如何与读入无关。
mmap()
允许您映射内存中的文件,但底层软件使用与
read()
实际使用的完全相同的机制从磁盘读取文件。唯一的区别(这使得
mmap()
比
read()
更好)是它直接将内核缓冲区映射到项目的虚拟内存空间。但这并没有使它变得更快,因为对用于映射的内存的访问仍然需要由内核监视,当您在分配给缓冲区的空间中写入时将缓冲区标记为脏(并且尊重您只写在数据区域,而不是在内务数据中)这意味着必须对您写入的内存进行一些映射,因此它实际上是写入与文件对应的内核缓冲区中,并且这必须使用与
copy_from
/
copy_to
中完成的复制类似的机制来完成读。事物经过优化以快速完成,但平均增益不是内存访问相对于磁盘访问的平均增益。此外,该文件必须可以
mmap()
这不是一般情况,例如NFS 文件无法映射(或不容易映射),套接字和管道无法映射,设备也无法映射。一般来说,无法
lseek()
d 的文件将无法被映射。