优化NUMA内存分配的核心是让CPU访问本地节点内存以降低延迟(约100ns)和避免远程访问(延迟高50%–200%);需先用numactl --hardware和numastat确认拓扑与失衡状态,再通过zone_reclaim_mode调优内核回收策略,并用numactl按进程绑定CPU与内存节点,配合taskset、大页等协同优化。

优化 NUMA 架构下的内存分配策略,核心是让 CPU 尽量访问本地节点(local node)的内存,减少跨节点(remote access)带来的延迟和带宽损耗。本地访问延迟通常在 100ns 左右,而远程访问可能高出 50%–200%,直接影响数据库、虚拟化、HPC 等对延迟敏感的应用性能。
确认 NUMA 拓扑与当前状态
动手调优前,必须先看清硬件布局:
- 运行 numactl --hardware 查看节点数量、每个 node 的 CPU 和内存分布、以及 node distances(数值越小表示越近)
- 用 numastat 观察各节点的内存使用情况,重点关注 numa_miss(本该本地分配却落到远端的次数)和 numa_foreign(本该远端但误分到本地)——这两个值持续偏高,说明分配已失衡
- 检查内核是否识别 NUMA:dmesg | grep -i numa,若输出含 “NUMA: Using …” 表示已启用;若为 “No NUMA configuration found”,需进 BIOS 开启 NUMA 支持
调整内核级内存回收行为
/proc/sys/vm/zone_reclaim_mode 控制内存不足时的应对逻辑,它直接影响是否容忍跨节点分配:
- 0(默认):允许跨 node 分配,不主动回收本地内存。适合多数通用场景,但易导致“本地内存耗尽、远端内存闲置”
- 1:本地内存不足时,只回收 page cache 中未映射(unmapped)的页面,开销轻,适合对延迟敏感且内存压力中等的服务
- 2 或 4:进一步回收需 writeback 或 swap 的页面,回收力度大但可能引发 I/O 抖动,慎用于数据库或实时服务
例如,为降低 MySQL 的远程访问概率,可临时设为 1:
echo 1 > /proc/sys/vm/zone_reclaim_mode
按进程粒度绑定 CPU 与内存节点
对关键应用(如 PostgreSQL、Redis、Java 服务),用 numactl 主动控制其“居住地”:
-
强制本地分配:
numactl --cpunodebind=0 --membind=0 your_command
确保进程只在 node 0 的 CPU 上运行,并且所有内存都从 node 0 分配 -
优先本地、允许备用(更灵活):
numactl --cpunodebind=0 --preferred=0 your_command
主用 node 0,本地内存不足时可 fallback 到其他 node,避免 OOM -
交错分配(适用于内存带宽密集型、访问均匀的场景,如科学计算):
numactl --interleave=all your_command
注意:若进程启动后派生子进程(如 fork),子进程默认继承父进程的 NUMA 策略;若需独立控制,应在子进程中重新调用 numactl 或设置进程级 policy(通过 set_mempolicy() 系统调用)。
配合 CPU 绑定与大页提升效果
单纯绑内存不够,还需协同调度:
- 用 taskset 或 numactl --cpunodebind 将进程固定在特定 node 的 CPU 上,避免因调度漂移到远端 CPU 导致后续访问变远程
- 启用透明大页(THP)或显式配置巨页(HugePages),减少 TLB miss,放大本地访问优势。尤其对 Redis、Elasticsearch 等内存密集型服务效果明显
- 对于容器环境(如 Docker),可在 run 时传入 --cpuset-cpus 和 --memory-swappiness=0,并挂载 /dev/hugepages,再结合 numactl 启动容器内主进程


















