#!/bin/bash
#
# This script parses /proc/meminfo and computes the level of
# "available" memory on the system. In this context, "available"
# means memory that can be re-used for something else.
#

declare -A mem_val

while read -a mem_item; do
  let mem_val["${mem_item[0]}"]=${mem_item[1]}
done </proc/meminfo

let mem_used=${mem_val["MemTotal:"]}-${mem_val["MemFree:"]}
let swap_used=${mem_val["SwapTotal:"]}-${mem_val["SwapFree:"]}
let mem_file=${mem_val["Active(file):"]}+${mem_val["Inactive(file):"]}
let mem_anon=${mem_val["Active(anon):"]}+${mem_val["Inactive(anon):"]}
let mem_avail=${mem_val["MemFree:"]}+$mem_file
let mem_unavail=${mem_val["MemTotal:"]}-$mem_avail

printf "%9s%11s%11s%11s%11s%11s%11s\n" \
       "" "total" "used" "free" "srecl" "act" "inact"

#
# Show the system memory in the same way as the "free" command.
#   total: MemTotal in /proc/meminfo
#   used:  MemTotal - MemFree
#   free:  MemFree
#   srecl: SReclaimable
#   act:   Active(file)
#   inact: Inactive(file)
# 
printf "%-9s%11d%11d%11d%11d%11d%11d\n" \
       "Mem:" ${mem_val["MemTotal:"]} $mem_used ${mem_val["MemFree:"]} \
       ${mem_val["SReclaimable:"]} ${mem_val["Active(file):"]} \
       ${mem_val["Inactive(file):"]}

#
# This line adjusts the amount of used/free memory based on what
# can be released under pressure.
#   used: MemTotal - MemFree - SReclaimable - Active(file) - Inactive(file)
#   free: MemFree + SReclaimable + Active(file) + Inactive(file)
#
# The Inactive(file) pages can just be released. The Active(file)
# pages must be flushed if dirty, then released. SReclaimable pages
# can be freed after a bit of slab crunching.
#
printf "%-18s%11d%11d\n" "-/+ srecl/act/inact:" $mem_unavail $mem_avail

#
# Show the swap-related memory info.
#   total: SwapTotal in /proc/meminfo
#   used:  SwapTotal - SwapFree
#   free:  SwapFree
#   srecl: not applicable
#   act:   Active(anon)
#   inact: Inactive(anon)
#
# The Active(anon) and Inactive(anon) pages are swap-backed. It
# means they can be swapped out under memory pressure provided
# there is room in the swap partition.
#
printf "%-9s%11d%11d%11d%11s%11d%11d\n" \
       "Swap:" ${mem_val["SwapTotal:"]} $swap_used ${mem_val["SwapFree:"]} \
       "" ${mem_val["Active(anon):"]} ${mem_val["Inactive(anon):"]}
