
Linux 内核 numastatNUMA 内存分配命中/未命中统计的深度解析【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux本文基于 Linux 内核官方文档 Documentation/admin-guide/numastat.rst系统讲解/sys/devices/system/node/node*/numastat接口下 6 个 NUMA 分配统计计数器的含义与语义并结合内核源码drivers/base/node.c、mm/vmstat.c剖析这些计数器是如何被采集和呈现的。读完本文你能够准确解读 NUMA 节点的内存分配行为进程是否从首选节点成功取到内存、评估 mempolicy 配置是否生效并识别 memoryless 节点带来的统计偏差。numastat 是什么每 NUMA 节点的分配命中统计numastat是内核为每个 NUMA 节点暴露的一个只读 sysfs 文件路径为/sys/devices/system/node/node*/numastat它的核心作用是反映进程从首选节点分配内存的成功程度。文档明确两点前提所有计数器的单位都是 page页Hugepages 有独立的计数器不与这些普通页计数器混算。也就是说当你cat /sys/devices/system/node/node0/numastat看到numa_hit 1234567时表示该节点上累计发生了 1234567 个普通页的命中分配事件而不是字节数。六大计数器语义详解内核文档给出了一张权威的定义表这里完整继承并结合语义背景展开计数器含义numa_hit进程想从本节点分配内存并且成功了numa_miss进程想从另一个节点分配内存最终却在本节点拿到了内存numa_foreign进程想从本节点分配内存最终却在另一个节点拿到了内存local_node进程运行在本节点的 CPU上并且内存也来自本节点other_node进程运行在别的节点的 CPU上最终却从本节点拿到了内存interleave_hitinterleave 内存策略想从本节点分配并且成功这 6 个计数器实际上来自两套观察视角理解这一点是正确解读数据的关键视角一以进程首选节点为锚点numa_hit / numa_miss / numa_foreignnuma_hit、numa_miss和numa_foreign三者是一组回答的问题是进程偏好的那个节点分配结果如何分配成功落在偏好节点上 → 在偏好节点上numa_hit加一分配成功但落在别的节点上 → 在偏好节点上numa_foreign加一我想要的地方没给我同时在实际成功分配的节点上numa_miss加一本没指望的节点反而给了我。因此对于一个节点的numa_foreign偏高通常意味着该节点内存紧张分配回落到远端节点而numa_miss偏高则说明它承接了大量外地需求的回落分配。文档同时指出通常偏好节点就是进程当前运行 CPU 所在的本地节点但 mempolicy 之类的限制会改变偏好节点。例如使用numactl --membind1运行进程后即使进程跑在 node0 的 CPU 上其偏好节点也是 node1此时的计数全部按 node1 的偏好来记账。视角二以CPU 本地节点为锚点local_node / other_nodelocal_node与other_node是独立于 mempolicy 的第二组它们不关心进程的偏好只看执行 CPU 与内存落点的相对位置local_node进程运行在本节点 CPU 上且内存取自本节点——即本地 CPU 本地内存的理想组合语义上类似numa_hitother_node进程运行在别的节点 CPU 上内存却取自本节点——即发生了跨节点内存访问语义上类似numa_miss。文档特别强调这一组没有与numa_foreign对应的计数器。因为foreign描述的是偏好落空而本地节点视角下我在本地 CPU 上跑、内存却去了远端这一事件并没有独立计数器去记在本地节点上它只会体现为远端节点上的other_node增量。interleave_hitinterleave 策略的专属计数interleave_hit专门为MPOL_INTERLEAVE内存交错策略服务当按 interleave 策略轮到本节点分配且成功时计数。它帮助你验证 interleave 策略是否按预期在多个节点间均匀落页。源码剖析计数器如何被采集与呈现sysfs 读取路径numastat文件的读取入口在 drivers/base/node.c 的node_read_numastat()static ssize_t node_read_numastat(struct device *dev, struct device_attribute *attr, char *buf) { fold_vm_numa_events(); return sysfs_emit(buf, numa_hit %lu\n numa_miss %lu\n numa_foreign %lu\n interleave_hit %lu\n local_node %lu\n other_node %lu\n, sum_zone_numa_event_state(dev-id, NUMA_HIT), sum_zone_numa_event_state(dev-id, NUMA_MISS), sum_zone_numa_event_state(dev-id, NUMA_FOREIGN), sum_zone_numa_event_state(dev-id, NUMA_INTERLEAVE_HIT), sum_zone_numa_event_state(dev-id, NUMA_LOCAL), sum_zone_numa_event_state(dev-id, NUMA_OTHER)); } static DEVICE_ATTR(numastat, 0444, node_read_numastat, NULL);从源码结构看有两点值得注意fold_vm_numa_events()这些 NUMA 事件平时分散记录在 per-CPU 的统计里读取前先调用该函数把各 CPU 上的计数折叠fold汇总到节点级统计保证 sysfs 读出的是完整累计值sum_zone_numa_event_state()按dev-id节点号将该节点下所有 zone 的NUMA_HIT、NUMA_MISS、NUMA_FOREIGN、NUMA_INTERLEAVE_HIT、NUMA_LOCAL、NUMA_OTHER六项事件状态求和后输出——这也解释了为什么文档强调单位是 page计数器累加的是分配成功的页数。该属性以只读0444方式注册static DEVICE_ATTR(numastat, 0444, node_read_numastat, NULL);事件名的定义事件枚举与展示名称定义在 vmstat 基础设施中例如 mm/vmstat.c 中可以看到[I(NUMA_HIT)] numa_hit这样的名称映射说明numastat与/proc/vmstat、节点vmstat文件中的 NUMA 事件统计共享同一套内核事件体系。同一节点下另有 drivers/base/node.c 的node_read_vmstat()会在CONFIG_NUMA下把所有 NUMA 事件逐项输出到节点级vmstat文件可作为交叉核对的补充视图。实用工具numastat 命令文档建议为了让输出更易读可以使用 numactl 软件包提供的numastat用户态工具。它会遍历所有节点把各节点的计数器排成对齐的表格典型用法numastat # 显示所有节点的完整统计 numastat -m # 以内存使用视角呈现 numastat -p pid # 观察特定进程的 NUMA 行为文档同时给出一条实用性提醒该工具目前只在 CPU 数量较少的机器上工作得比较好CPU 很多时per-CPU 计数折叠与表格输出的呈现会打折扣大型系统建议直接读取 sysfs 文件。解读实战如何判断 NUMA 分配健康状况结合上述语义一个典型的健康度判读流程是看偏好视角对每个节点numa_hit应显著大于numa_foreign。若某节点numa_foreign持续增长说明进程频繁首选该节点却拿不到内存可能原因是该节点内存耗尽或被 mempolicy 限死分配回落到远端看本地视角local_node应远大于other_node。other_node高意味着大量跨节点内存访问会带来跨 NUMA 的访存延迟区分 mempolicy 影响由于numa_*三计数以偏好节点为锚若你给进程设置了--membind或set_mempolicy()需先确认偏好节点是哪个再按对应节点的计数来解读否则会误判核对 hugepages这些计数器只统计普通页大页分配量需要用 hugepages 相关独立计数器如节点 meminfo 中的 HugePages 统计另行核对。重要陷阱memoryless 节点会扭曲统计文档给出了一个必须知道的内核实现细节在含有memoryless 节点有 CPU 但没有内存的节点的系统中numa_hit、numa_miss、numa_foreign三项统计会被严重扭曲skewed heavily。机理如下引用文档原文语义当前内核实现中如果一个进程偏好一个 memoryless 节点例如它正运行在该节点本地 CPU 上内核实际上会把最近的、带内存的节点当作真正的偏好节点来处理分配。其后果是memoryless 节点自身不会增加numa_foreign因为内核根本不把它当落空的偏好这些分配的记账全部转移到了最近的带内存节点上从而扭曲该最近节点的 numa_hit / numa_miss / numa_foreign 统计。因此在 memoryless 节点拓扑常见于某些 NUMA 服务器与 CXL 内存扩展场景上做性能分析时应优先依赖local_node/other_node这组不受偏好节点替换逻辑影响的计数并结合硬件拓扑如numactl -H来定位真实瓶颈。小结/sys/devices/system/node/node*/numastat提供 6 个以页为单位的计数器分属偏好节点视角numa_hit/miss/foreign、interleave_hit与CPU 本地节点视角local_node/other_node两套观察体系hugepages 另计内核侧由 drivers/base/node.c 的node_read_numastat()汇总 per-CPU NUMA 事件后输出事件体系与 mm/vmstat.c 中的 vmstat 名称表一致使用 numactl 的numastat工具可快速获得可读输出但大型系统上直接读 sysfs 更可靠在含 memoryless 节点的系统上numa_*三项计数会因偏好节点被替换为最近带内存节点而失真解读时应优先使用local_node/other_node。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考