从C程序中测量页面错误。

13

我正在比较几个系统调用,其中我从/向内存读写。是否有定义的API来测量C中的页面错误(页面进出)?

我找到了这个库libperfstat.a,但它是为AIX而设计的,我找不到任何适用于Linux的东西。

编辑: 我知道在Linux中有timeperf-stat命令,只是探索是否有任何可供我在C程序中使用的东西。


1
这不是一个C库,但你可以使用 time -v a.out 命令来显示关于你的程序的大量信息,包括页面错误。 - Daniel
在链接的第一行中,它说“C编程语言子程序的集合”。我知道time命令,但是正在探索是否可以从C程序内部完成任何操作。不过还是谢谢! - brokenfoot
“在C程序中对我可用。”-- 你能容忍不准确吗?可能没有太多的API,因为它定义得很差(在进入和退出此系统调用时可能会发生故障,所以您希望它从何时开始报告?)。 - Brian Cain
@BrianCain:同意,但是在看到AIX库之后,我很好奇是否存在类似的Linux库。我想我将不得不使用perf stat - brokenfoot
不要失去希望,Linux中没有库来完成这个任务的原因是可以轻松地在没有库的情况下完成它,请参见我下面的答案。 - Vality
3个回答

10
如果你在使用Linux操作系统,你可以使用perf_event_open系统调用(被perf stat使用)。获取正确的参数可能会有些棘手,可以查看这个man page并参考下面的代码。因为没有lib C包装器,所以你需要按照以下方式调用:
static long perf_event_open(struct perf_event_attr *hw_event,
                pid_t pid,
                int cpu,
                int group_fd,
                unsigned long flags) {
  int ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
            group_fd, flags);
  return ret;
}

然后计算页面错误:

  struct perf_event_attr pe_attr_page_faults;
  memset(&pe_attr_page_faults, 0, sizeof(pe_attr_page_faults));
  pe_attr_page_faults.size = sizeof(pe_attr_page_faults);
  pe_attr_page_faults.type =   PERF_TYPE_SOFTWARE;
  pe_attr_page_faults.config = PERF_COUNT_SW_PAGE_FAULTS;
  pe_attr_page_faults.disabled = 1;
  pe_attr_page_faults.exclude_kernel = 1;
  int page_faults_fd = perf_event_open(&pe_attr_page_faults, 0, CPU, -1, 0);
  if (page_faults_fd == -1) {
    printf("perf_event_open failed for page faults: %s\n", strerror(errno));
    return -1;
  }

  // Start counting
  ioctl(page_faults_fd, PERF_EVENT_IOC_RESET, 0);
  ioctl(page_faults_fd, PERF_EVENT_IOC_ENABLE, 0);

  // Your code to be profiled here 
  .....

  // Stop counting and read value
  ioctl(page_faults_fd, PERF_EVENT_IOC_DISABLE, 0);
  uint64_t page_faults_count;
  read(page_faults_fd, &page_faults_count, sizeof(page_faults_count));

这是一个不错的建议,但需要注意它没有 C 绑定。 - Vality
是的,我还没有时间在这里写包装代码。 - Manuel Selva
CPU 宏未定义。 -1 是常见的默认值。 - lorcap

5

有一个名为getrusage的函数(SVr4,4.3BSD,POSIX.1-2001; 但并非所有字段都在标准中定义)。在Linux中,存在一些损坏的字段,但是man getrusage列出了几个有趣的字段:

long   ru_minflt;        /* page reclaims (soft page faults) */
long   ru_majflt;        /* page faults (hard page faults) */

long   ru_inblock;       /* block input operations */
long   ru_oublock;       /* block output operations */

rusagewait4 中也有报告(仅限于外部程序使用)。/usr/bin/time 程序使用此选项(可打印次要/主要页面错误计数)。


工作得非常好 :) ! 谢谢! - brokenfoot
ru_inblock/ru_oublock在清空页面缓存后是否计算了您的read()请求? - osgx
1
是的,那个线性扩展了。块输入操作= 8(文件大小为1K)到块输入操作= 2234992(文件大小为1G):) - brokenfoot

3

这并不是一个API,但我曾通过自己的方法在我的C程序中读取/proc/myPID/stat文件,并获得了进程的页面错误统计信息。这使我能够监控程序运行时的计数,并以任何我喜欢的方式存储这些数据。

请记住,这样做可能会导致产生页面错误本身,因此会存在一定的不准确性,但你可以得到一个大致的概念。

有关文件格式的详细信息,请参见此处:https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_MRG/1.3/html/Realtime_Reference_Guide/chap-Realtime_Reference_Guide-Memory_allocation.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接