Linux Memory Management: Understanding Kernel Samepage Merging (KSM)

·

Keywords: KSM, Anonymous Pages, COW, madvise, MERGEABLE, UNMERGEABLE

Kernel Samepage Merging (KSM) is a Linux memory management feature designed to merge identical pages, optimizing memory usage in virtualized environments and other scenarios where duplicate content exists across processes.

How KSM Works

KSM enables the merging of identical anonymous pages—both within a single process and across different processes—without affecting application functionality. This is achieved by:

  1. Creating a single read-only copy of identical pages
  2. Freeing up the original physical pages
  3. Triggering Copy-On-Write (COW) when applications need to modify the merged page

Core Implementation Components

KSM's architecture consists of two main parts:

  1. The ksmd kernel thread that scans and merges pages when activated
  2. The madvise system call that triggers ksmd to begin its work
Userspace interaction flow:
madvise(addr, length, MADV_MERGEABLE) → __ksm_enter() → wakes ksmd
madvise(addr, length, MADV_UNMERGEABLE) → stops merging for specified pages

KSM Implementation Details

Page Eligibility

KSM specifically targets anonymous pages allocated by processes. These include:

Note: KSM does not merge:

Data Structures

KSM uses three primary data structures:

  1. struct rmap_item: Tracks reverse mappings for virtual addresses
  2. struct mm_slot: Represents process memory structures being scanned
  3. struct ksm_scan: Maintains current scanning state
Key relationships:
mm_slot → rmap_list → rmap_item
ksm_scan tracks current position in scanning process

The Merging Process

The ksmd thread follows this workflow:

  1. Scanning: Iterates through eligible memory regions
  2. Comparison: Checks page content against stable and unstable trees
  3. Merging: When matches found, creates merged pages and updates mappings
ksm_do_scan()
├── scan_get_next_rmap_item()  # Finds next candidate page
└── cmp_and_merge_page()       # Attempts to merge page
    ├── stable_tree_search()   # Checks stable tree
    ├── try_to_merge_with_ksm_page()
    ├── unstable_tree_search_insert()
    └── try_to_merge_two_pages()

KSM vs Regular Anonymous Pages

Identification Differences

Anonymous pages and KSM pages are distinguished by their mapping flags:

Page TypeMapping Flags
Regular AnonPAGE_MAPPING_ANON
KSM PagePAGE_MAPPING_ANON + PAGE_MAPPING_KSM

Address Calculation Differences

For regular anonymous pages:

For KSM pages:

👉 Learn more about Linux memory management techniques

Enabling and Configuring KSM

Kernel Configuration

KSM must be enabled via kernel config:

CONFIG_KSM=y

Runtime Control via sysfs

KSM provides several tunable parameters in /sys/kernel/mm/ksm/:

ParameterDescriptionDefault Value
pages_to_scanPages scanned per iteration100
sleep_millisecsDelay between scans20
runControls KSM operation (0=off, 1=on)0
merge_across_nodesAllow merging across NUMA nodes1

Performance Considerations

Monitoring KSM Effectiveness

Key metrics to evaluate KSM performance:

Performance Indicators:

FAQ

Q: Does KSM impact application performance?
A: KSM operates transparently with minimal overhead. The main cost comes from scanning pages, which is configurable via pages_to_scan and sleep_millisecs.

Q: When should I disable KSM?
A: Consider disabling KSM when:

Q: Can KSM merge pages from different NUMA nodes?
A: Yes, unless merge_across_nodes is set to 0, which restricts merging to pages within the same NUMA node.

Q: How does KSM handle writes to merged pages?
A: Writing to a merged page triggers COW (Copy-On-Write), creating a private copy for the writing process while maintaining other mappings to the original page.

Q: What types of workloads benefit most from KSM?
A: Virtualized environments running multiple similar VMs see the most benefit, as do systems running multiple instances of the same application.

👉 Explore advanced memory optimization techniques

Best Practices

  1. Monitor effectiveness: Regularly check KSM statistics to ensure it's providing value
  2. Tune parameters: Adjust pages_to_scan and sleep_millisecs based on workload
  3. Consider NUMA: For NUMA systems, evaluate merge_across_nodes setting
  4. Selective enabling: Use madvise(MADV_MERGEABLE) for specific memory regions rather than system-wide

Conclusion