Skip to content

Instantly share code, notes, and snippets.

@awreece
Created March 3, 2015 19:15
Show Gist options
  • Save awreece/427ff5dc58b531615f4f to your computer and use it in GitHub Desktop.
Save awreece/427ff5dc58b531615f4f to your computer and use it in GitHub Desktop.
/*
* This was a grand experiment - I would evaluate students based on the only
* meaningful metric, amount of memory they actually used. This would make slab
* allocators more interesting, as they could potentially be more efficient in
* larger programs. Unfortunately, it is *exceptionally* hard to measure the
* current memory usage of a program, and even harder to do so portably.
*
* The most promising approach was getrusage(2). This library call is available
* on Mac OSX and Linux, and offers the ability to get the maximum resident set
* size. At first blush this was promising, but unfortunately there were some
* complications. First the units for ru_maxrss are consistent accross
* platforms: on MacOSX the man page claims the unit is bytes, whereas on Linux
* the man page claims the unit is kilobytes. Even worse, getusage(2) does not
* interact in a clean way with mmap(2). For the following sequnce of operation,
* the program will likely print the same value of ru_maxrss both times:
*
* getrusage(RUSAGE_SELF, &usage);
* printf("%ld\n", usage.ru_maxrss);
* memset(mmap(NULL, 4096*10, PROT_WRITE|PROT_READ,
* MAP_ANONYMOUS|MAP_PRIVATE, 0, 0), 'A', 4096*10);
* getrusage(RUSAGE_SELF, &usage);
* printf("%ld\n", usage.ru_maxrss);
*
* Nearest I can tell, this is because ru_maxrss does not relate to the current
* resident set size.
*
* I then took a different tack: abandoning my dreams of a cross platform
* assignment, I chose to use /proc/self/statm from the proc(5) file-system.
* This was more promising, as it returned the actual resident set size.
* Unfortunately, this still did not interact cleanly with mmap. The following
* program will likely the same value from resident_bytes() every time:
*
* memlib_mmap(4096*1000);
* printf("%ld\n", resident_bytes());
* memlib_mmap(4096*1000);
* printf("%ld\n", resident_bytes());
* memset(memlib_mmap(4096*10), 'A', 4096*10)
* printf("%ld\n", resident_bytes());
*
* Interestingly, if the last mmap size is 4096*1000, the resident memory as
* calculated by /proc/self/statm changes. It is unclear why this is or in
* what way the new value is related to the previous sequence of operations.
*/
UNUSED static long
resident_bytes()
{
int ret;
long size, resident, share, text, lib, data, dirty;
char buf[1024];
(void) read_file("/proc/self/statm", buf, sizeof (buf));
ret = sscanf(buf, "%ld %ld %ld %ld %ld %ld %ld",
&size, &resident, &share, &text, &lib, &data, &dirty);
VERIFY3S(ret, ==, 7);
return (resident * 4096);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment