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:
- The same memory might be counted in multiple categories
- Shared libraries appear in SHR but also contribute to RES
- 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