Linux – How to Get Available Memory Across Distributions

linuxmeminfomemory

The standard files/tools that report memory seem to have different formats on different Linux distributions. For example, on Arch and Ubuntu.

  • Arch

    $ free
                  total        used        free      shared  buff/cache   available
    Mem:        8169312     3870392     2648348       97884     1650572     4110336
    Swap:      16777212      389588    16387624
    
    
    $ head /proc/meminfo 
    MemTotal:        8169312 kB
    MemFree:         2625668 kB
    MemAvailable:    4088520 kB
    Buffers:          239688 kB
    Cached:          1224520 kB
    SwapCached:        17452 kB
    Active:          4074548 kB
    Inactive:        1035716 kB
    Active(anon):    3247948 kB
    Inactive(anon):   497684 kB
    
  • Ubuntu

    $ free
                 total       used       free     shared    buffers     cached
    Mem:      80642828   69076080   11566748    3063796     150688   58358264
    -/+ buffers/cache:   10567128   70075700
    Swap:     20971516    5828472   15143044
    
    
    $ head /proc/meminfo 
    MemTotal:       80642828 kB
    MemFree:        11565936 kB
    Buffers:          150688 kB
    Cached:         58358264 kB
    SwapCached:      2173912 kB
    Active:         27305364 kB
    Inactive:       40004480 kB
    Active(anon):    7584320 kB
    Inactive(anon):  4280400 kB
    Active(file):   19721044 kB
    

So, how can I portably (across Linux distros only) and reliably get the amount of memory—excluding swap—that is available for my software to use at a particular time? Presumably that's what's shown as "available" and "MemAvailable" in the output of free and cat /proc/meminfo in Arch but how do I get the same in Ubuntu or another distribution?

Best Answer

MemAvailable is included in /proc/meminfo since version 3.14 of the kernel; it was added by commit 34e431b0a. That's the determining factor in the output variations you show. The commit message indicates how to estimate available memory without MemAvailable:

Currently, the amount of memory that is available for a new workload, without pushing the system into swap, can be estimated from MemFree, Active(file), Inactive(file), and SReclaimable, as well as the "low" watermarks from /proc/zoneinfo.

The low watermarks are the level beneath which the system will swap. So in the absence of MemAvailable you can at least add up the values given for MemFree, Active(file), Inactive(file) and SReclaimable (whichever are present in /proc/meminfo), and subtract the low watermarks from /proc/zoneinfo. The latter also lists the number of free pages per zone, that might be useful as a comparison...

The complete algorithm is given in the patch to meminfo.c and seems reasonably easy to adapt:

  • sum the low watermarks across all zones;
  • take the identified free memory (MemFree);
  • subtract the low watermark (we need to avoid touching that to avoid swapping);
  • add the amount of memory we can use from the page cache (sum of Active(file) and Inactive(file)): that's the amount of memory used by the page cache, minus either half the page cache, or the low watermark, whichever is smaller;
  • add the amount of memory we can reclaim (SReclaimable), following the same algorithm.

So, putting all this together, you can get the memory available for a new process with:

awk -v low=$(grep low /proc/zoneinfo | awk '{k+=$2}END{print k}') \
 '{a[$1]=$2}
  END{ 
   print a["MemFree:"]+a["Active(file):"]+a["Inactive(file):"]+a["SReclaimable:"]-(12*low); 
  }' /proc/meminfo 
Related Question