Skip to content

Commit

Permalink
fix PSS graph on recent kernels
Browse files Browse the repository at this point in the history
It seems the smaps file layout in /proc changed in some kernel version.
This commit fix it by:
- Using smaps_rollup (available since kernel 4.14) instead of smaps to
  avoid having to loop over all entries (smaps_rollup being a summary
  of smaps).

- If smaps_rollup is not available (kernel < 4.14), use smaps instead as
  before and sum all PSS lines.

- Searching "Pss:" instead of using hardcoded offsets (which will
  probably go wrong again in the future).

Fixes: #46
  • Loading branch information
amurzeau authored and bluca committed Aug 28, 2023
1 parent 93609bf commit b8c1c50
Showing 1 changed file with 19 additions and 39 deletions.
58 changes: 19 additions & 39 deletions src/store.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
* read() overhead.
*/
static char smaps_buf[4096];
static int skip = 0;

double gettime_ns(void) {
struct timespec n;
Expand Down Expand Up @@ -489,55 +488,36 @@ int log_sample(DIR *proc,

/* Pss */
if (!ps->smaps) {
sprintf(filename, "%d/smaps", pid);
/* smaps_rollup was introduced in kernel 4.14 */
sprintf(filename, "%d/smaps_rollup", pid);
fd = openat(procfd, filename, O_RDONLY|O_CLOEXEC);
if (fd < 0) {
sprintf(filename, "%d/smaps", pid);
/* If we can't open smaps_rollup, try with smaps */
fd = openat(procfd, filename, O_RDONLY|O_CLOEXEC);
}
if (fd < 0)
continue;
goto catch_rename;
ps->smaps = fdopen(fd, "re");
if (!ps->smaps) {
close(fd);
continue;
goto catch_rename;
}
setvbuf(ps->smaps, smaps_buf, _IOFBF, sizeof(smaps_buf));
} else {
rewind(ps->smaps);
}

/* test to see if we need to skip another field */
if (skip == 0) {
if (fgets(buf, sizeof(buf), ps->smaps) == NULL) {
continue;
}
if (fread(buf, 1, 28 * 15, ps->smaps) != (28 * 15)) {
continue;
}
if (buf[392] == 'V') {
skip = 2;
}
else {
skip = 1;
}
rewind(ps->smaps);
}

while (1) {
int pss_kb;

/* skip one line, this contains the object mapped. */
if (fgets(buf, sizeof(buf), ps->smaps) == NULL) {
break;
}
/* then there's a 28 char 14 line block */
if (fread(buf, 1, 28 * 14, ps->smaps) != 28 * 14) {
break;
}
pss_kb = atoi(&buf[61]);
ps->sample->pss += pss_kb;

/* skip one more line if this is a newer kernel */
if (skip == 2) {
if (fgets(buf, sizeof(buf), ps->smaps) == NULL)
break;
/* Sum all 'Pss:' lines (this is needed when we are not
* reading smaps_rollup).
* When reading smaps_rollup, only one 'Pss:' entry will be
* present.
*/
ps->sample->pss = 0;
while (fgets(buf, sizeof(buf), ps->smaps) != NULL) {
if(strncmp(buf, "Pss:", 4) == 0) {
/* read the Pss line */
ps->sample->pss += atoi(buf + 4);
}
}

Expand Down

0 comments on commit b8c1c50

Please sign in to comment.