How to Calculate Accurate Memory Usage Percentage from vmstat Output in Linux


2 views

When working with vmstat, it's crucial to understand that its memory columns represent different aspects of memory utilization:

swpd  - Amount of virtual memory used (KB)
free  - Idle memory (KB)
buff  - Memory used as buffers (KB)
cache - Memory used as cache (KB)

The main confusion arises because vmstat doesn't directly show total physical memory. Unlike top or free, you need to calculate it:

total_memory = free + buff + cache + used_memory

However, vmstat doesn't display the "used_memory" directly. Here's how to derive it:

From your example output:

procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0 139728  45396 199128 1236360    1    2     4   622    3    1 51  4 43  2  0

Here's the calculation script:

#!/bin/bash

# Get memory info from vmstat
vmstat_output=$(vmstat -s)

# Extract values
total_memory=$(echo "$vmstat_output" | grep "total memory" | awk '{print $1}')
used_memory=$(echo "$vmstat_output" | grep "used memory" | awk '{print $1}')

# Calculate percentage
memory_usage_percentage=$(echo "scale=2; ($used_memory/$total_memory)*100" | bc)

echo "Memory Usage: ${memory_usage_percentage}%"

For more accurate results, use vmstat -s which provides memory statistics in a parseable format:

vmstat -s | grep -E "total memory|used memory"

Sample output:

4059616 K total memory
3965504 K used memory
45396 K free memory
199128 K buffer memory
1236360 K cache memory

The discrepancy occurs because:

  • top includes kernel memory in its calculations
  • vmstat reports raw memory statistics without kernel allocations
  • Buffers and cache handling differs between tools

For continuous monitoring, use this script that calculates memory usage percentage:

#!/bin/bash

while true; do
    vmstat_data=$(vmstat -s)
    total=$(echo "$vmstat_data" | awk '/total memory/ {print $1}')
    used=$(echo "$vmstat_data" | awk '/used memory/ {print $1}')
    perc=$(echo "scale=2; $used*100/$total" | bc)
    echo "$(date) - Memory Usage: $perc%"
    sleep 5
done

Remember that Linux uses available memory aggressively for caching. High memory usage shown in vmstat might not indicate a real problem - the cache can be freed when applications need memory.


When analyzing memory usage through vmstat, it's crucial to understand the exact meaning of each memory-related field:

-----------memory----------
swpd   free   buff  cache
139728 45396 199128 1236360
  • swpd: Amount of swap memory used (in kB)
  • free: Idle memory (unallocated RAM)
  • buff: Memory used as buffers
  • cache: Memory used as page cache

The key observation is that vmstat doesn't directly display total physical memory. While you might think to sum swpd + free + buff + cache, this approach has flaws:

# This naive calculation would be incorrect:
swpd + free + buff + cache = 1620612 kB (~1.62 GB)
# While 'top' shows 4059616 kB (~4.06 GB) total

To accurately calculate memory usage percentage from vmstat, you need:

  1. Total physical memory (must be obtained separately)
  2. Correct formula for used memory

Here's a Bash script that combines vmstat with free to get the percentage:

#!/bin/bash

# Get total memory
TOTAL_MEM=$(free -k | awk '/Mem:/ {print $2}')

# Get memory stats from vmstat
read SWPD FREE BUFF CACHE < <(vmstat -s | awk '
    /used swap/ {swpd=$1}
    /free memory/ {free=$1}
    /buffer memory/ {buff=$1}
    /cache/ {cache=$1}
    END {print swpd, free, buff, cache}')

# Calculate used memory (excluding buffers/cache as they're reclaimable)
USED_MEM=$((TOTAL_MEM - FREE - BUFF - CACHE))

# Calculate percentage
MEM_USAGE_PERCENT=$((USED_MEM * 100 / TOTAL_MEM))

echo "Memory Usage: ${MEM_USAGE_PERCENT}%"

Another approach using /proc/meminfo for total memory:

# Get total memory from /proc
TOTAL=$(awk '/MemTotal/ {print $2}' /proc/meminfo)

# Get available memory from vmstat
AVAILABLE=$(vmstat -s | awk '/free memory/ {print $1}')

USED=$((TOTAL - AVAILABLE))
PERCENT=$((USED * 100 / TOTAL))

echo "Used: ${PERCENT}%"

The fundamental limitation is that vmstat was designed primarily for monitoring system activity and performance statistics, not for comprehensive memory reporting. For accurate memory percentage calculations, you need to:

  • Combine with other tools (free, /proc/meminfo)
  • Understand what constitutes "used" vs "available" memory
  • Account for buffers and cache differently depending on your needs

For enterprise monitoring systems, consider this robust implementation:

#!/bin/bash
# Returns memory usage percentage from vmstat-like sources

get_mem_stats() {
  # Try various methods to get memory info
  if [ -f /proc/meminfo ]; then
    read _ TOTAL _ FREE _ BUFF _ CACHE _ < <(awk '
      /MemTotal/ {t=$2}
      /MemFree/ {f=$2}
      /Buffers/ {b=$2}
      /Cached/ {c=$2}
      END {print t, f, b, c}' /proc/meminfo)
  elif which free >/dev/null; then
    read TOTAL USED FREE SHARED BUFF CACHE < <(free -k | awk '/Mem:/ {print $2,$3,$4,$5,$6,$7}')
  else
    echo "Error: No memory info available" >&2
    exit 1
  fi
}

get_mem_stats

# Calculate used memory (adjust formula as needed)
USED=$((TOTAL - FREE - BUFF - CACHE))
PERCENT=$((USED * 100 / TOTAL))

echo "$PERCENT"