Created
March 17, 2011 13:50
-
-
Save dolmen/874335 to your computer and use it in GitHub Desktop.
A new implementation of Node's Platform::GetMemory (in src/platform_linux.cc)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* A new implementation of Node's Platform::GetMemory (in src/platform_linux.cc) */ | |
/* Copyright (c) 2011 Olivier Mengué */ | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <sys/param.h> // MAXPATHLEN | |
#include <fcntl.h> // O_RDONLY | |
#include <sys/time.h> // gettimeofday | |
typedef enum { | |
false = 0, | |
true = 1 | |
} bool; | |
static char buf[MAXPATHLEN + 1]; | |
// From NodeJs: src/platform_linux.cc | |
int GetMemory(size_t *rss, size_t *vsize) { | |
FILE *f = fopen("/proc/self/stat", "r"); | |
if (!f) return -1; | |
int itmp; | |
char ctmp; | |
size_t page_size = getpagesize(); | |
char *cbuf; | |
bool foundExeEnd; | |
/* PID */ | |
if (fscanf(f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* Exec file */ | |
cbuf = buf; | |
foundExeEnd = false; | |
if (fscanf (f, "%c", cbuf++) == 0) goto error; // ( | |
while (1) { | |
if (fscanf(f, "%c", cbuf) == 0) goto error; | |
if (*cbuf == ')') { | |
foundExeEnd = true; | |
} else if (foundExeEnd && *cbuf == ' ') { | |
*cbuf = 0; | |
break; | |
} | |
cbuf++; | |
} | |
/* State */ | |
if (fscanf (f, "%c ", &ctmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* Parent process */ | |
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* Process group */ | |
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* Session id */ | |
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* TTY */ | |
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* TTY owner process group */ | |
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* Flags */ | |
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* Minor faults (no memory page) */ | |
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* Minor faults, children */ | |
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* Major faults (memory page faults) */ | |
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* Major faults, children */ | |
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* utime */ | |
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* stime */ | |
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* utime, children */ | |
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* stime, children */ | |
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* jiffies remaining in current time slice */ | |
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* 'nice' value */ | |
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* jiffies until next timeout */ | |
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* jiffies until next SIGALRM */ | |
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* start time (jiffies since system boot) */ | |
if (fscanf (f, "%d ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* Virtual memory size */ | |
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
*vsize = (size_t) itmp; | |
/* Resident set size */ | |
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
*rss = (size_t) itmp * page_size; | |
/* rlim */ | |
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* Start of text */ | |
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* End of text */ | |
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
/* Start of stack */ | |
if (fscanf (f, "%u ", &itmp) == 0) goto error; /* coverity[secure_coding] */ | |
fclose (f); | |
return 0; | |
error: | |
fclose (f); | |
return -1; | |
} | |
int GetMemory2(size_t *rss, size_t *vsize) { | |
// See proc(5) manual | |
FILE *f = fopen("/proc/self/stat", "r"); | |
if (!f) return -1; | |
int i; | |
int c; | |
// skip pid | |
c = fgetc(f); | |
if (c < '1' || c > '9') goto error; | |
do { | |
if ((c = fgetc(f)) == EOF) goto error; | |
} while (c >= '0' && c <= '9'); | |
if (c != ' ') goto error; | |
if ((c = fgetc(f)) == EOF || c != '(') goto error; | |
// skip process name | |
do { | |
if ((c = fgetc(f)) == EOF) goto error; | |
} while (c != ')'); | |
if ((c = fgetc(f)) == EOF || c != ' ') goto error; | |
// skip 20 columns | |
for(i=0; i<20; i++) { | |
do { | |
if ((c = fgetc(f)) == EOF) goto error; | |
if (c == ')') goto error; // the process name breaks parsing | |
} while (c != ' '); | |
} | |
// read vsize | |
size_t value = 0; | |
while (1) { | |
if ((c = fgetc(f)) == EOF) goto error; | |
if (c == ' ') break; | |
if (c < '0' || c > '9') goto error; | |
value = value * 10 + (c - '0'); | |
} | |
*vsize = value; | |
// read rss | |
value = 0; | |
while (1) { | |
if ((c = fgetc(f)) == EOF) goto error; | |
if (c == ' ') break; | |
if (c < '0' || c > '9') goto error; | |
value = value * 10 + (c - '0'); | |
} | |
*rss = value * getpagesize(); | |
fclose(f); | |
return 0; | |
error: | |
*rss = *vsize = 0; | |
fclose(f); | |
return -1; | |
} | |
int GetMemory3(size_t *rss, size_t *vsize) { | |
// See proc(5) manual | |
int fd = open("/proc/self/stat", O_RDONLY); | |
if (fd < 0) return -1; | |
char buf[512]; | |
ssize_t len = read(fd, buf, sizeof(buf)); | |
close(fd); | |
if (len == sizeof(buf)) | |
buf[sizeof(buf)-1] = '\n'; | |
if (len <= 0 || buf[len-1] != '\n') goto error; | |
//if (len < 40) goto error; | |
char *p = buf; | |
if (*p < '1' || *p > '9') goto error; | |
do { | |
if (*++p == '\n') goto error; | |
} while (*p >= '0' && *p <= '9'); | |
if (*p != ' ') goto error; | |
if (*++p != '(') goto error; | |
// skip process name | |
do { | |
if (*++p == '\n') goto error; | |
} while (*p != ')'); | |
if (*++p != ' ') goto error; | |
// skip 20 columns | |
int i; | |
for(i=0; i<20; i++) { | |
do { | |
if (*++p == '\n') goto error; | |
if (*p == ')') goto error; // the process name breaks parsing | |
} while (*p != ' '); | |
} | |
// read vsize | |
size_t value = 0; | |
int c; | |
while (1) { | |
c = *++p; | |
if (c == ' ') break; | |
if (c < '0' || c > '9') goto error; | |
value = value * 10 + (c - '0'); | |
} | |
*vsize = value; | |
// read rss | |
value = 0; | |
while (1) { | |
c = *++p; | |
if (c == ' ') break; | |
if (c < '0' || c > '9') goto error; | |
value = value * 10 + (c - '0'); | |
} | |
*rss = value * getpagesize(); | |
return 0; | |
error: | |
*rss = *vsize = 0; | |
return -1; | |
} | |
typedef int (*GetMemory_func)(size_t *rss, size_t *vsize); | |
void test(GetMemory_func func) | |
{ | |
struct timeval start, stop, diff; | |
size_t rss = 0, vsize = 0; | |
gettimeofday(&start, NULL); | |
int res = GetMemory(&rss, &vsize); | |
res = GetMemory(&rss, &vsize); | |
res = GetMemory(&rss, &vsize); | |
gettimeofday(&stop, NULL); | |
time_t sec = stop.tv_sec - start.tv_sec; | |
int usec = (int)stop.tv_usec - (int)start.tv_usec; | |
if (usec < 0) { | |
sec--; | |
usec += 1000000; | |
} | |
printf("%ld.%06d res = %d, rss = %zd, vsize = %zd\n", sec, usec, res, rss, vsize); | |
} | |
int main() { | |
FILE *f = fopen("/proc/self/stat", "r"); | |
char s[2048]; | |
fputs(fgets(s, sizeof(s), f), stdout); | |
fclose(f); | |
test(GetMemory); | |
test(GetMemory); | |
test(GetMemory2); | |
test(GetMemory3); | |
void * p = malloc(10*1024*1024); | |
test(GetMemory); | |
test(GetMemory2); | |
test(GetMemory3); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment