How to Accurately Interpret Memory Usage Metrics in htop for Process Analysis


3 views

When analyzing memory usage in htop, you'll see several columns representing different memory metrics:

VIRT  - Virtual memory size (total address space)
RES   - Resident memory (physical RAM used)
SHR   - Shared memory (shared libraries)
%MEM  - Memory percentage of total RAM
CODE  - Executable code memory
DATA  - Heap + stack allocations

To determine actual physical memory consumption (RAM), focus on these metrics:

RES (Resident Set Size) - Non-swapped physical memory
SHR (Shared Memory) - Potentially shared with other processes

For the Ruby process example showing:

VIRT=1234M RES=51M SHR=8M %MEM=3.1 CODE=51M DATA=1M

The true physical memory impact would be approximately RES (51MB). The shared memory (8MB) might be counted toward other processes as well.

For a more accurate calculation of a process's unique memory footprint:

Unique Memory ≈ RES - (SHR * sharing_factor)

Example Python script to calculate this:

def calculate_unique_memory(res_mb, shr_mb, sharing_factor=0.5):
    """Estimate unique memory consumption"""
    return res_mb - (shr_mb * sharing_factor)

# For our Ruby process:
print(calculate_unique_memory(51, 8))  # Output: 47 MB

For deeper investigation, combine htop with other tools:

# Get detailed memory map for a process
pmap -x <pid>

# Show shared memory segments
ipcs -m

# Monitor memory changes in real-time
watch -n 1 'ps -p <pid> -o rss,sz,vsz'

1. Don't sum all memory columns - they overlap
2. VIRT includes memory-mapped files and unused address space
3. RES includes shared libraries already counted by other processes
4. %MEM is relative to total system memory, not container limits

When debugging memory issues:

# Find memory leaks with valgrind
valgrind --tool=memcheck --leak-check=full ruby script.rb

# Profile Ruby memory with
rbtrace -p <pid> -m 'GC.stat'

Remember that interpreted languages like Ruby often show higher memory usage due to their runtime environment.


When analyzing memory usage in htop for a Ruby process (or any process), you'll typically see several memory-related columns. The key columns are:

VIRT  RES  SHR  %MEM  CODE  DATA
3.2G  51M  8M   1.3%  1M    51M

For the Ruby process in your example (showing 3+1+8+51+51), here's what each number represents:

  • VIRT (3.2G): Total virtual memory (address space) allocated
  • RES (51M): Resident memory - actual physical RAM being used
  • SHR (8M): Shared memory - memory shared with other processes
  • CODE (1M): Memory used for executable code
  • DATA (51M): Memory used for data (heap and stack)

For determining physical memory usage, focus on:

RES - SHR = Private memory usage
51M - 8M = 43M

This gives you the actual physical memory exclusively used by your Ruby process.

You can get similar information programmatically using Ruby's own process status:

# Get process memory in Ruby
def process_memory
  ps -o rss= -p #{Process.pid}.to_i / 1024
end

puts "Current memory usage: #{process_memory} MB"

The multiple numbers can be confusing because:

  1. The same memory might be counted in multiple categories
  2. Shared libraries appear in SHR but also contribute to RES
  3. Virtual memory (VIRT) is often much larger than physical usage

For deeper analysis of Ruby memory usage, consider these tools:

# Install memory_profiler gem
require 'memory_profiler'

report = Memory_profiler.report do
  # Your code here
end
report.pretty_print

This gives you object-level memory allocation details beyond what htop shows.

  • For physical memory usage, look at RES (minus SHR if you want private memory)
  • DATA shows heap usage which is often the main memory consumer
  • Ruby processes often show higher VIRT than RES due to memory mapping