在 Linux 环境下,并没有一个现成的“内存带宽利用率”指标可以直接查看。当你打开 /proc/meminfo、free、vmstat 时,看到的仅仅是内存用量和页面活动状况,而非 DRAM 实际读写速率。要想获取实时内存带宽数据,必须借助 perf 或 Intel 的 PCM 工具链才能实现。

perf stat 可测量 DDR 实际读写速率,但事件名称需根据 CPU 型号确认
在 Intel 平台上,最通用的方法是直接使用 perf 读取内存控制器(uncore)的性能计数器。关键不在于死记命令,而是先确认当前 CPU 支持哪些具体事件:
- 执行
perf list | grep -i memory查看可用事件,重点关注类似uncore_imc_00/event=0x04,umask=0x0f/(DDR 读)和uncore_imc_00/event=0x05,umask=0x0f/(DDR 写)的条目。 - 不同微架构的事件编码存在差异:Skylake 和 Ice Lake 的 event code 并不相同,直接套用会报
event is not supported错误。 - 单次采样示例:
sudo perf stat -e uncore_imc_00/event=0x04,umask=0x0f/,uncore_imc_00/event=0x05,umask=0x0f/ -I 1000 -a sleep 5,输出结果中两列数字分别表示采样周期内的读/写字节数,除以时间再换算为 MB/s(除以 1024²)。 - 默认仅监控 socket 0;多路服务器需添加
-a参数,并手动解析每个uncore_imc_*设备(例如uncore_imc_01)。
pcm-memory.x 输出可读的带宽摘要,但仅支持 Intel 且对版本有要求
Intel PCM 工具链中的 pcm-memory.x 是最接近“开箱即用”的解决方案,但它并非系统自带组件,也不兼容 AMD 平台:
- 必须从 GitHub opcm/pcm 下载源码自行编译,
apt install intel-cmt-cat并不包含完整的 PCM 工具链。 - 运行
sudo ./pcm-memory.x 1后,直接查看MEM READ和MEM WRITE列,单位是 GB/s;顶部还会显示理论峰值带宽(如Max Memory Bandwidth: 51.2 GB/s)。 - Sapphire Rapids 等新平台需要使用 PCM v5.13 以上版本,旧版本可能将带宽读成 0 或报错
Failed to detect memory controller。 - 该工具默认聚合所有内存通道,但不会区分 NUMA 节点——跨节点访问的实际延迟和隐性竞争情况,
pcm-memory.x完全不体现。
free/vmstat 的“内存使用率”与带宽毫无关联
很多人误以为 free -h 中 available 接近 0 就代表带宽已被打满,这是一种典型的认知混淆:
free中的used是内核统计的“已分配页”,并不包含硬件层面的突发访存压力。- 一个仅占用 2GB 物理内存的程序,如果进行密集随机访问(例如 hash join 配合大 buffer pool),照样能占满 DDR 带宽,但
free显示一切正常。 vmstat中的si/so反映的是 swap I/O,bi/bo反映的是块设备 I/O,两者都与内存控制器吞吐量无关。- 真正与内存带宽相关的硬件事件包括:DRAM read/write cycles、memory controller queue depth——这些指标只能通过
perf或 PCM 工具来捕获。
内存带宽并非单一数值:在多通道架构下,每个 channel 独立计数;在 NUMA 架构中,跨节点访问会引入额外延迟和隐性带宽争抢,而绝大多数工具默认只报告 socket 0 或聚合值,这容易掩盖真实的瓶颈点。
