Really used memory on GNU/Linux

Classé dans : informatique | 0 commentaire(s)

19
06 | 14

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.

cutting memory in two: used, not used

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

cutting memory in two: used, not used

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.

Ecrire un commentaire

La vérification anti-spam a échoué




Quelle est la dernière lettre du mot ayhu ? :