Computing Total and Free RAM in Linux with Qt
It is sometimes useful to measure the amount of free memory while your app is running. I typically do this to ensure there is no memory leak, for example. Even a small amount of leaked memory may be a problem for applications that are supposed to run for long time, without downtime. Instead of writing this each and every time, I added a function to my utils library here.
Computation
Computing “free” memory is not entirely trivial. Memory management is a bit complex. However, this is what I came up with. First, let’s define:
MemTotal ($T$): total usable ram (i.e. physical ram minus a few reserved
bits and the kernel binary code).MemFree ($F$): the sum of LowFree+HighFree, where lowmem is memory which can be used for everything that highmem can be used for, but it is also available for the kernel’s use for its own data structures. Among many other things, it is where everything from the Slab is allocated. Bad things happen when you’re out of lowmem. Highmem is all memory above ~860MB of physical memory. Highmem areas are for use by userspace programs, or for the pagecache. The kernel must use tricks to access this memory, making it slower to access than lowmem.
Buffers ($B$): relatively temporary storage for raw disk blocks shouldn’t get tremendously large (20MB or so).
Cached ($C$): in-memory cache for files read from the disk (the pagecache). Doesn’t include SwapCached.
SReclaimable ($R$): part of Slab, that might be reclaimed, such as caches.
Slab: in-kernel data structures cache.
https://www.kernel.org/doc/Documentation/filesystems/proc.txt
Data is provided in /proc/meminfo
. For example:
> cat /proc/meminfo MemTotal: 16344972 kB MemFree: 13634064 kB MemAvailable: 14836172 kB Buffers: 3656 kB Cached: 1195708 kB SwapCached: 0 kB Active: 891636 kB Inactive: 1077224 kB HighTotal: 15597528 kB HighFree: 13629632 kB LowTotal: 747444 kB LowFree: 4432 kB SwapTotal: 0 kB SwapFree: 0 kB Dirty: 968 kB Writeback: 0 kB AnonPages: 861800 kB Mapped: 280372 kB Shmem: 644 kB KReclaimable: 168048 kB Slab: 284364 kB SReclaimable: 159856 kB SUnreclaim: 124508 kB PageTables: 24448 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 7669796 kB Committed_AS: 100056 kB VmallocTotal: 112216 kB VmallocUsed: 428 kB VmallocChunk: 111088 kB Percpu: 62080 kB HardwareCorrupted: 0 kB AnonHugePages: 49152 kB ShmemHugePages: 0 kB ShmemPmdMapped: 0 kB
By reading kernel sources, it seems kB is the only unit allowed in the file and kB is intended as kibibytes: https://github.com/torvalds/linux/blob/v6.7/fs/proc/meminfo.c#L28.
Total usable memory, part of which is clearly already used, is simply $T$. Computing available memory ($A$), instead, is a bit more convoluted. By “available memory”, I mean unused or, however, allocatable. According to most sources, this is how it can be computed, in bytes, as:
$$A=\frac{(F+B+C+R)}{1024}$$
This is what htop does. free is implemented like this instead.
How to Use
Simply run the function and read the result:
#include <lqtutils_system.h> std::optional<lqt::MemData> mem = lqt::read_mem_data(); if (mem) { qInfo() << "Total:" << QLocale::system().formattedDataSize(mem->totalMemBytes); qInfo() << "Free :" << QLocale::system().formattedDataSize(mem->freeMemBytes); }
Have fun! 😉