The Math Behind the Configuration
Guessing at vm.nr_hugepages leads to either wasted reserved memory or application startup failures. Here is the systematic approach.
The formula:
nr_hugepages = ceil(application_memory_bytes / hugepage_size_bytes) + overhead_buffer
Worked example — Postgres with 32GB shared_buffers:
Application memory: 32 GB = 32 × 1024 MB = 32,768 MB
HugePage size: 2 MB
Pages required: 32,768 / 2 = 16,384 pages
Buffer (1%): ~164 pages
Final value: 16,548 → round up to 16,600
Applying that calculated value is the same vm.nr_hugepages sysctl write, and HugePages_Total in /proc/meminfo confirms whether the kernel actually honored the full request.
Why add a buffer? The kernel may fail to allocate the exact number requested if memory is fragmented. Requesting slightly more than needed ensures the application gets what it needs even if a few pages cannot be allocated. A 1–5% buffer is typical.
Timing matters: HugePage allocation is easiest immediately after boot, before memory becomes fragmented. On a server that has been running for weeks, requesting 16,600 contiguous 2MB-aligned blocks may partially fail. The kernel will allocate as many as it can and report the actual count in HugePages_Total. If HugePages_Total is less than requested, you need to either reboot or trigger the kernel's memory compaction mechanism (/proc/sys/vm/compact_memory) before retrying the allocation.
Checking how much memory an application actually needs: For Postgres, the relevant setting is shared_buffers in postgresql.conf. For Java, it is -Xmx (max heap). For Redis, it is maxmemory. Always calculate based on the configured limit, not current usage — the application may grow into its full allocation.