For a few months now I've been rebuffed, being told “there's no single answer” when asking for a way to calculate the “really used memory” on my GNU/Linux system.
Obviously `free` wasn't giving what I wanted, since I was reaching OOM conditions when it said I was using 14% of my RAM (hint: big tmpfs). Of course, that's if you look at the “±buffers/cache” line. If however you look at the first line, it seems you're always almost out of memory! (hint: disk cache)
Not very satisfying, but today I finally got it right.
Thanks to Munin's memory graphs, which helped me make sense of some variables in /proc/meminfo, so that I knew how to count the used RAM.

On my machine, imagine that Shmem is a few centimeters higher. So it looks a bit more like this:

Turns out it's the free RAM that's easy to count, so the answer is:
Used RAM = MemTotal - (MemFree+Buffers+SReclaimable+Cached-Shmem)
Here's a shell script that does correctly what `free` does wrong:
#!/bin/sh div=1 unit=K [ "${1}" = '-m' ] && unit=M && div=1024 [ "${1}" = '-g' ] && unit=G && div=$((1024*1024)) eval "$(sed 's/^\([^:]*\):[[:space:]]*\([0-9]*\).*$/\1=\2/;s/(//;s/)//' /proc/meminfo)" echo "total $((MemTotal/div))${unit} used $(( ( MemTotal - (MemFree+Buffers+SReclaimable+Cached-Shmem) ) / div ))${unit}"
Implementation in C is here
And here's a conky patch:
--- conky-1.9.0/src/linux.c.old 2014-06-18 11:05:42.965999512 +0200 +++ conky-1.9.0/src/linux.c 2014-06-18 23:57:32.601326864 +0200 @@ -159,7 +159,8 @@ FILE *meminfo_fp; static int rep = 0; - /* unsigned int a; */ + unsigned long long shmem, sreclaimable; + char buf[256]; info.mem = info.memmax = info.swap = info.swapfree = info.swapmax = info.bufmem = @@ -186,6 +187,11 @@ sscanf(buf, "%*s %llu", &info.buffers); } else if (strncmp(buf, "Cached:", 7) == 0) { sscanf(buf, "%*s %llu", &info.cached); + + } else if (strncmp(buf, "Shmem:", 6) == 0) { + sscanf(buf, "%*s %llu", &shmem); + } else if (strncmp(buf, "SReclaimable:", 13) == 0) { + sscanf(buf, "%*s %llu", &sreclaimable); } } @@ -193,7 +199,16 @@ info.memeasyfree = info.memfree; info.swap = info.swapmax - info.swapfree; - info.bufmem = info.cached + info.buffers; + /* Reclaimable memory: does not include shared memory, which is part of cached but unreclaimable. + Includes the reclaimable part of the Slab cache though. + Note: when shared memory is swapped out, shmem decreases and swapfree decreases - we want this. + */ + info.bufmem = (info.cached - shmem) + info.buffers + sreclaimable; + + /* Now (info.mem - info.bufmem) is the *really used* (aka unreclaimable) memory. + When this value reaches the size of the physical RAM, and swap is full or non-present, OOM happens. + Therefore this is the value that the user wants to monitor, regarding their RAM. + */ fclose(meminfo_fp); return 0;
Edit: reported, pull-requested, merged.
Here we go! I don't know if a patch for `free` would be envisionable, but probably for such a system tool it wouldn't make sense.
For those wondering: this post is in English because I wanted English-speaking developers and users to be able to read it.