Understanding Virtual Memory vs. Swap Usage in htop: Why Gigabyte VIRT Shows Zero SWP


4 views

When monitoring system resources on OS X (now macOS) using htop, many developers encounter a puzzling scenario where processes show massive virtual memory (VIRT) allocations but zero swap (Swp) usage. This seems counterintuitive since we'd expect memory pressure when virtual memory grows.

Mem[|||||||||||||||||||||3872/4096MB]
Swp[                           0/0MB]

PID USER     VIRT   RES   SHR
284 501     15.3G 1064M     0

The key misunderstanding lies in what the VIRT column actually represents. Virtual memory includes:

  • Allocated but unused address space
  • Memory-mapped files
  • Shared libraries
  • Actually resident memory (RES)

Modern systems (including OS X) use demand-paged virtual memory. The 15.3GB VIRT for Firefox doesn't mean it's using 15.3GB of physical resources - it's just address space the process could potentially use.

When physical memory (RAM) becomes constrained, macOS uses several mechanisms before touching swap:

// Example of memory pressure handling in macOS
1. Compressor (transparent memory compression)
2. Purgeable memory (cached files)
3. App memory trimming
4. Finally, swap to disk

To get accurate memory measurements, focus on these metrics instead:

// Useful macOS commands:
vm_stat # Shows virtual memory statistics
top -l 1 -o mem # Processes sorted by memory
sysctl vm.swapusage # Swap space details

The RES (resident memory) column in htop shows what's actually in physical RAM. In our example, Firefox uses 1064MB resident memory despite its 15.3GB virtual size.

Swap becomes active when:

  • Physical memory is exhausted after compression
  • Inactive pages need to be moved out
  • System maintains free memory buffer

You can force swap usage test with this Python script:

import numpy as np
# Allocate 1GB chunks until swap activates
arrays = []
while True:
    arrays.append(np.zeros(1024**3, dtype=np.uint8))

For deeper macOS memory analysis, consider:

vmmap -interleaved [pid] # Detailed process memory map
memory_pressure # Memory pressure monitoring
heap -s [pid] # Heap analysis

Remember that htop's swap display (Swp) only shows actively used swap space, not allocated swap files which may exist but remain unused.


When examining the htop output on OS X 10.6.8, we see processes consuming gigabytes of virtual memory (VIRT) while showing zero swap usage (Swp[0/0MB]). This apparent contradiction stems from fundamental differences between virtual memory management and actual swap space utilization.

The VIRT column represents the total address space allocated to a process, including:

  • Memory-mapped files
  • Shared libraries
  • Reserved but unused address ranges
  • Actually committed physical RAM

This Python script demonstrates how virtual memory allocation works without physical commitment:

import mmap

# Allocate 1GB virtual address space without physical RAM
with open("/dev/zero", "r+b") as f:
    # MAP_PRIVATE means copy-on-write, no physical allocation yet
    mem = mmap.mmap(f.fileno(), 1024*1024*1024, mmap.MAP_PRIVATE)
    print(f"Allocated 1GB virtual address space (PID: {os.getpid()})")
    input("Press Enter to exit...")

Swap space only comes into play when:

  1. The system is under memory pressure
  2. The kernel needs to page out inactive memory pages
  3. Processes request more memory than physically available

Sample C code that would actually trigger swap usage:

#include 
#include 

int main() {
    const size_t gb = 1024*1024*1024;
    char *buffer = malloc(gb);
    
    if (!buffer) {
        perror("malloc failed");
        return 1;
    }
    
    // Actually touch every page to force physical allocation
    for (size_t i = 0; i < gb; i += 4096) {
        buffer[i] = 1;
    }
    
    printf("Allocated and touched 1GB of memory (PID: %d)\n", getpid());
    getchar();
    free(buffer);
    return 0;
}

Several factors contribute to what you're seeing:

Factor Impact
Memory compression OS X compresses inactive pages instead of swapping
Shared libraries Counted in VIRT but shared across processes
Memory-mapped files Appear in VIRT but don't consume RAM/swap
Overcommit behavior Linux allows overallocation while BSD systems are more conservative

To get more detailed memory information on OS X:

# Show memory pressure statistics
vm_stat

# Detailed process memory breakdown
vmmap <pid>

# Show swap usage (even if zero)
sysctl vm.swapusage

For Linux systems, you could use:

# Detailed process memory info
pmap -x <pid>

# Show page faults (minor faults don't trigger swap)
ps -o min_flt,maj_flt <pid>