Memory management
Memory management is a fun thing. Think about the following:
You have a program running on your computer and you want to know how big its memory footprint is. Half of the program has not yet been loaded from disk, a quarter has been swapped out of main memory. The rest is using 200k of shared libraries and has 1 megabyte in the file system cache that can be freed up with no serious consequences. If you are interested in this kind of things, this article is for you :)
File system cache
Linux tends to fill up all your computer's memory over time. This is not bad, but works as designed. Whenever Linux reads a file from disk, it keeps the content in memory so it does not have to wait for the disk next time. This is called the file system cache, you can display its size with the command
# free total used free shared buffers cached Mem: 6083904 1175880 4908024 0 7556 230460 -/+ buffers/cache: 937864 5146040 Swap: 0 0 0
If you really want to clean the file system cache, you will probably want to clean dentries and inodes as well, you can do it with the commands:
sync echo 3 > /proc/sys/vm/drop_caches
page size
Ok, first I want to find out my system's page size so I write a program:
#include <unistd.h> #include <stdio.h> int main() { int sz = getpagesize(); printf("%d",sz); }
And compile it:
# gcc main.c
And execute it:
# ./a.out 4096
Ok, so my system's page size is 4K.
Now let's write the next program and check how much memory it consumes. Here is the code:
int main() { while (1); }
Compile it
# gcc main.c
And execute it in the background:
# ./a.out & [5] 24058
Ok, it's process ID is 24058. Let's look at its memory consumption:
# pmap 24058 24058: a.out START SIZE RSS PSS DIRTY SWAP PERM MAPPING 0000000000400000 4K 4K 4K 0K 0K r-xp /home/tstaerk/test/a.out 0000000000600000 4K 4K 4K 4K 0K r--p /home/tstaerk/test/a.out 0000000000601000 4K 4K 4K 4K 0K rw-p /home/tstaerk/test/a.out 00007fda6f01e000 1364K 160K 1K 0K 0K r-xp /lib64/libc-2.11.1.so 00007fda6f173000 2044K 0K 0K 0K 0K ---p /lib64/libc-2.11.1.so 00007fda6f372000 16K 16K 16K 16K 0K r--p /lib64/libc-2.11.1.so 00007fda6f376000 4K 4K 4K 4K 0K rw-p /lib64/libc-2.11.1.so 00007fda6f377000 20K 12K 12K 12K 0K rw-p [anon] 00007fda6f37c000 124K 104K 1K 0K 0K r-xp /lib64/ld-2.11.1.so 00007fda6f55a000 12K 12K 12K 12K 0K rw-p [anon] 00007fda6f599000 4K 4K 4K 4K 0K rw-p [anon] 00007fda6f59a000 4K 4K 4K 4K 0K r--p /lib64/ld-2.11.1.so 00007fda6f59b000 4K 4K 4K 4K 0K rw-p /lib64/ld-2.11.1.so 00007fda6f59c000 4K 4K 4K 4K 0K rw-p [anon] 00007fff625e5000 84K 12K 12K 12K 0K rw-p [stack] 00007fff625ff000 4K 4K 0K 0K 0K r-xp [vdso] ffffffffff600000 4K 0K 0K 0K 0K r-xp [vsyscall] Total: 3704K 352K 86K 80K 0K 136K writable-private, 3568K readonly-private, 0K shared, and 352K referenced
Ok, it looks like the binary has a lot of shared libraries that it makes use of. Let's see if this is true:
# ldd a.out linux-vdso.so.1 => (0x00007fffc4bee000) libc.so.6 => /lib64/libc.so.6 (0x00007f2c6cc78000) /lib64/ld-linux-x86-64.so.2 (0x00007f2c6d013000)
It is true, it is a dynamically-linked executable. Let's make it a static one:
# gcc --static main.c # ll a.out -rwxr-xr-x 1 tstaerk users 2947494 2012-06-06 10:14 a.out
And run it again:
# ./a.out & [7] 21850
And look at its memory map again:
# pmap 21850 21850: a.out START SIZE RSS PSS DIRTY SWAP PERM MAPPING 0000000000400000 572K 84K 84K 0K 0K r-xp /home/tstaerk/test/a.out 000000000068e000 8K 8K 8K 8K 0K rw-p /home/tstaerk/test/a.out 0000000000690000 152K 20K 20K 20K 0K rw-p [heap] 00007fff34f2f000 84K 8K 8K 8K 0K rw-p [stack] 00007fff34f56000 4K 0K 0K 0K 0K r-xp [vdso] ffffffffff600000 4K 0K 0K 0K 0K r-xp [vsyscall] Total: 824K 120K 120K 36K 0K 244K writable-private, 580K readonly-private, 0K shared, and 120K referenced