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


12 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"