Measure page faults from a c program
Asked Answered
O

3

14

I am comparing a few system calls where I read/write from/to memory. Is there any API defined to measure page faults (pages in/out) in C ?

I found this library libperfstat.a but it is for AIX, I couldn't find anything for linux.

Edit: I am aware of time & perf-stat commands in linux, just exploring if there is anything available for me to use inside the C program.

Oviparous answered 25/4, 2014 at 20:49 Comment(5)
This is not a C library but you can use time -v a.out to display a plethora of info about your program, including page faults.Creedon
In the 1st line of the link it says "collection of C programming language subroutines". I know about the time command, but was exploring if anything can be done from inside the C program. Thanks though!Oviparous
" available for me inside the C program." -- can you tolerate inaccuracy? There's probably not much of an API for this because it's so poorly defined (faults can happen on your way into and out of this system call, so as of when do you want it to report?).Kamerad
@BrianCain: Agree, but after seeing the AIX library, I got curious if something similar exists for linux. I guess I'll have to use perf stat.Oviparous
Dont lose hope, the reason there is no library in linux to do this is that it is trivial to do it without, please see my answer below.Sulfite
S
5

There is getrusage function (SVr4, 4.3BSD. POSIX.1-2001; but not all fields are defined in standard). In linux there are several broken fields, but man getrusage lists several interesting fields:

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 */

The rusage is also reported in wait4 (only usable in external program). This one is used by /usr/bin/time program (it prints minor/major pagefault counts).

Scenarist answered 27/4, 2014 at 0:7 Comment(3)
Worked beautifully :) ! Thank you!Oviparous
Did ru_inblock/ru_oublock count your read() requests after emptying pagecache?Scenarist
Yes, that scaled linearly. block input operations=8 (file size 1K) to block input operations=2234992 (file size 1G) :)Oviparous
T
10

If you are running on Linux, you can use the perf_event_open system call (used by perf stat). It's a little bit tricky to get the right parameters, look at the man page http://web.eece.maine.edu/~vweaver/projects/perf_events/perf_event_open.html and see the code below.

There is no lib C wrapper so you have to call it as following:

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;
}

and then to count page faults:

  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));
Triphylite answered 26/4, 2014 at 8:49 Comment(3)
Thats a good one, you may want to note it has no C binding however.Sulfite
Yes I didn't had time yet to write down the wrapper code here.Triphylite
CPU macro is not defined. -1 is a common default.Rancourt
S
5

There is getrusage function (SVr4, 4.3BSD. POSIX.1-2001; but not all fields are defined in standard). In linux there are several broken fields, but man getrusage lists several interesting fields:

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 */

The rusage is also reported in wait4 (only usable in external program). This one is used by /usr/bin/time program (it prints minor/major pagefault counts).

Scenarist answered 27/4, 2014 at 0:7 Comment(3)
Worked beautifully :) ! Thank you!Oviparous
Did ru_inblock/ru_oublock count your read() requests after emptying pagecache?Scenarist
Yes, that scaled linearly. block input operations=8 (file size 1K) to block input operations=2234992 (file size 1G) :)Oviparous
S
3

It is not an API as such, however I have had a lot of success by rolling my own and reading /proc/myPID/stat from within my C program which includes page fault statistics for my process, this allows me to monitor counts in real time as my program runs and store these however I like.

Remember that doing so can cause page faults in itself so there will be some inaccuracy but you will get a general idea.

See here for details of the format of the file: 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

Sulfite answered 25/4, 2014 at 22:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.