Transparent Hugepages and Kernel Samepage Merging on a VPS: Latency Effects Measured

Two kernel memory features are enabled by default on most Linux distributions and quietly change latency characteristics in opposite directions. Transparent Hugepages (THP) reduces TLB misses by backing memory with 2 MB pages. Kernel Samepage Merging (KSM) deduplicates identical memory pages across processes to save RAM. On a VPS, both interact with virtualisation in ways that are worth measuring rather than assuming.

Check What Your Kernel Is Actually Doing

# Transparent Hugepages state
cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag

# Kernel Samepage Merging
cat /sys/kernel/mm/ksm/run
cat /sys/kernel/mm/ksm/pages_shared
cat /sys/kernel/mm/ksm/pages_sharing

# Per-process hugepage usage
grep -i huge /proc/meminfo

Interpretation matters here. THP has three main states: always, madvise, and never. KSM has a run value of 0 (off), 1 (on and scanning), or 2 (on but not started until a process opts in via madvise).

Why THP Is a Latency Risk for Databases

THP’s benefit is fewer TLB misses for large, sequentially-accessed working sets. Its cost is allocation latency. When the kernel needs a 2 MB page and none is available, it attempts compaction of physical memory — and that compaction can stall the allocating process for milliseconds to tens of milliseconds.

For a database with a latency-sensitive commit path, a multi-millisecond stall is worse than the TLB savings. This is why PostgreSQL, MySQL, and Redis documentation have all historically recommended madvise or never for THP:

# Persistent setting via kernel boot parameters
# Add to GRUB_CMDLINE_LINUX_DEFAULT:
#   transparent_hugepage=madvise
# Then: sudo update-grub && sudo reboot

# Runtime (non-persistent) for testing:
echo madvise | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo defer   | sudo tee /sys/kernel/mm/transparent_hugepage/defrag

Setting defrag to defer is the low-risk middle ground: pages are still merged opportunistically in the background, but no process is blocked waiting for compaction.

KSM on a VPS: Deduplication That Costs CPU

KSM scans memory pages and merges those with identical content into a single copy-on-write page. On a host running many similar VMs, this can reclaim substantial RAM — which is why hosts sometimes enable it even when your guest has it disabled.

The trade-off is CPU. The scanning daemon consumes cycles, and when a merged page is written, the guest takes a copy-on-write fault. Those faults are usually fast, but under memory pressure with thousands of merged pages, they add up.

SettingRAM effectCPU effectLatency risk
THP alwaysMay use more RAM per mappingLower TLB overheadHigh — compaction stalls
THP madviseNeutralNeutralLow
KSM onFrees duplicate pagesScan + COW fault overheadLow to moderate
KSM offNoneNoneNone

Measuring the Impact on Your Workload

Do not change these settings based on general advice. Measure your own server. A simple before/after procedure:

  1. Record a baseline. Run your normal workload and capture latency percentiles — for a database, pgbench or sysbench; for a web app, request p95 and p99 from your access log.
  2. Check the current state and note it.
  3. Change one setting at a time. Toggle THP to madvise first, re-run the benchmark, compare.
  4. Then toggle KSM and repeat. Do not change both at once or you cannot attribute the effect.
  5. Watch pages_sharing after enabling KSM — if it stays near zero, the feature is costing CPU for no benefit on your workload.

For latency-sensitive databases, the common configuration is THP set to madvise with defrag=defer, and KSM left off in the guest unless memory pressure is demonstrable. For memory-constrained multi-tenant workloads — several small containers on one VPS — KSM enabled in the guest can reclaim real RAM at an acceptable CPU cost.

Interaction With Virtualisation

Inside a KVM guest, the host decides whether to back your guest memory with hugepages at its own level. Your guest-level THP setting controls only what the guest kernel requests from the virtualised MMU. The host’s own THP policy can still introduce latency you cannot see from inside. This is one more reason to measure end-to-end response time rather than reasoning from guest settings alone. A host that enables aggressive host-level THP can produce latency spikes in your guest that no amount of guest-level tuning will remove, because you are seeing the effect of host memory compaction on the physical pages backing your VM.

Detecting a Host-Level Stall

If your application shows periodic latency spikes that do not correlate with your own CPU, disk, or memory activity, check two things. First, whether the spikes align with a regular interval such as 30 or 60 seconds, which often indicates a periodic host operation. Second, whether steal time in mpstat rises at the same moments. If steal rises while your guest’s own CPU usage is flat, the stall originated outside your VM.

You cannot fix a host-level policy from inside the guest, but you can prove it is happening and raise it with evidence. What you can control is your own configuration: monitor compact_stall and compact_fail counters in /proc/vmstat. A rising compact_stall count is direct evidence that allocation is blocking on memory compaction, which correlates closely with THP-induced latency.

# Direct evidence of compaction-induced stalls
grep -E 'compact_stall|compact_fail|compact_success' /proc/vmstat

# Steal time while a latency spike is occurring
mpstat 1 20 | tail -20

If compact_stall is climbing, the fix is the guest-side THP change to madvise with defer, which stops the kernel performing synchronous compaction in the allocation path. That single change removes the most common in-guest source of multi-millisecond pauses.

When you rent a full-virtualisation instance such as those at virtualserversvps.com, you have your own kernel and can set these parameters directly rather than depending on a shared host’s policy — which makes this class of tuning both possible and worth doing.

Recommendations

  • Database and latency-sensitive servers: THP madvise, defrag defer, KSM off.
  • Memory-constrained multi-service boxes: KSM on, verify pages_sharing is non-trivial.
  • Compute-heavy workloads with large sequential working sets: THP always can genuinely help — measure before dismissing it.
  • Always benchmark rather than applying defaults from a blog post, including this one.

Leave a Reply