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:
- The system is under memory pressure
- The kernel needs to page out inactive memory pages
- 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>