title: 内存测试
created: 2026-06-20
updated: 2026-06-20
type: concept
tags: [memory, benchmark, stress-test]
sources:
- raw/scripts/0内存.sh
- raw/scripts/mem.sh
- raw/scripts/mlc.sh
内存测试
内存测试涵盖信息查看、带宽/延迟基准测试和稳定性压力测试三大类。本文重点解析 STREAM 基准测试的各项指标。
1. 内存基本信息查看
dmidecode
通过 DMI/SMBIOS 读取物理内存硬件信息:
sudo dmidecode -t memory # 查看所有内存信息
sudo dmidecode -t 16 # 查看物理内存阵列
sudo dmidecode -t 17 | awk -F': ' '
BEGIN {
printf "%-5s %-15s %-20s %-25s %-10s\n", "Line", "Locator", "Serial", "Size-Type-Speed", "Part Number"
}
/Size:/ { size = $2 }
/Bank Locator:/ { locator = $2 }
/Type:/ { type = $2 }
/Configured Memory Speed:/ { speed = $2 }
/Serial Number:/ { serial = $2 }
/Part Number:/ { part = $2 }
/Firmware Version:/ {
combined = size "-" type "-" speed
printf "%-5d %-15s %-20s %-25s %-10s\n", line++, locator, serial, combined, part
}'
关键字段解读:
- Size — 单条容量(如 32 GB)
- Type — 内存类型(DDR4 / DDR5 / DDR3)
- Configured Memory Speed — 运行频率(如 3200 MT/s)
- Part Number — 部件号,用于确认厂商和型号
free -h
快速查看系统内存使用概览:
free -h
输出包括总容量(total)、已用(used)、可用(available)、缓存/缓冲区(buff/cache)等。
lsmem
查看内存布局和每个内存块的状态:
lsmem
显示每个内存段的起始地址、结束地址、大小、状态(online/offline)和 zone(如 Movable)。
内存缓存清理
在测试前清理页缓存、dentry 和 inode 缓存,避免缓存内容影响内存或磁盘测试结果:
echo 3 > /proc/sys/vm/drop_caches
说明:写入
1只清理页缓存,写入2清理 dentries/inodes,写入3清理全部(最彻底)。在 STREAM 等内存带宽测试和 FIO/iozone 磁盘测试前均应执行。参见:cpu-testing(测试前后清理缓存)、disk-storage-testing(磁盘测试前必须清理)
2. STREAM 内存带宽基准测试
STREAM 是业界最主流的内存带宽测试工具,通过四种向量运算操作测量可持续内存带宽。
获取与编译
curl -OL http://www.cs.virginia.edu/stream/FTP/Code/stream.c
gcc -fopenmp \
-mtune=native -march=native \
-O3 \
-DSTREAM_ARRAY_SIZE=100000000 \
-DNTIMES=100 \
-DOFFSET=4096 \
-mcmodel=medium \
stream.c -o stream
编译参数详解:
| 参数 | 说明 |
|---|---|
-fopenmp |
启用 OpenMP 多线程支持,默认线程数等于 CPU 逻辑核心数 |
-mtune=native -march=native |
针对当前 CPU 指令集优化(ARM 平台需取消) |
-O3 |
最高编译优化级别 |
-DSTREAM_ARRAY_SIZE=N |
数组大小(元素个数),建议 ≥ L3 缓存大小 × 4 / 8,确保内存压力而非缓存命中 |
-DNTIMES=N |
每项运算重复次数,取最优值(建议 100+),越大结果越稳定 |
-DOFFSET=N |
数组偏移量(可选),用于避免缓存行争用 |
-mcmodel=medium |
当数组大小超过 2 GB 时需要,解除大内存限制 |
数组大小计算推荐:
# 自动根据 L3 缓存计算数组大小
gcc -fopenmp -O3 -march=native -mtune=native \
-DNTIMES=100 \
-DSTREAM_ARRAY_SIZE=$(lscpu | awk '/L3/{sz=$3; u=$4; if(u=="MiB")sz=sz*1024*1024; else if(u=="KiB")sz=sz*1024; print int(sz/8/3)}') \
-DOFFSET=0 -DSTATIC= stream.c -o stream
运行与绑核
# 清理缓存
echo 3 > /proc/sys/vm/drop_caches
# 多线程(默认使用所有 CPU 核心)
export OMP_NUM_THREADS=$(lscpu | awk '/CPU\(s\):/{printf("%d\n",$2)}' | grep -v 0)
./stream
# 单线程(对比测试)
export OMP_NUM_THREADS=1
./stream
# 绑核运行(避免跨 NUMA 节点调度)
export GOMP_CPU_AFFINITY=0-127
四项指标详解
STREAM 输出四个核心指标,单位均为 MB/s:
| 指标 | 运算操作 | 含义 | 典型特征 |
|---|---|---|---|
| Copy | c[i] = a[i] |
仅读+写,纯内存带宽 | 通常最高值,接近理论带宽的 80-90% |
| Scale | b[i] = scalar × c[i] |
读+乘法+写 | 略低于 Copy(多了 ALU 操作开销) |
| Add | c[i] = a[i] + b[i] |
读两个数组+加法+写 | 比 Copy 稍低(需要两倍读取带宽) |
| Triad | a[i] = b[i] + scalar × c[i] |
乘+加混合(最接近实际负载) | 业界最广泛引用的综合带宽指标 |
结果解读:
-------------------------------------------------------------
Function Best Rate MB/s Avg time Min time Max time
Copy: 51234.5 0.015625 0.014203 0.017302
Scale: 50876.2 0.015756 0.014312 0.017890
Add: 53421.8 0.023451 0.020310 0.025109
Triad: 53100.3 0.023402 0.020430 0.025401
-------------------------------------------------------------
- Best Rate MB/s — 多次运行中的最优值(受 NTIMES 控制)
- 理论带宽估算:
DDR 频率 × 8 字节 × 通道数 × 1/1000,例如 DDR4-3200 双通道 ≈ 3200 × 8 × 2 = 51.2 GB/s。Triad 实测值达到理论值 80% 以上即表现正常。 - 对比场景:
- 单线程 vs 多线程 — 评估内存带宽对多核扩展性
- 多插槽(NUMA)交叉访问 — 远端内存带宽通常为近端的 50-70%
批量运行与结果提取
# 三次运行取稳定值
echo "" > stream.out
for i in {1..3}
do
echo 3 > /proc/sys/vm/drop_caches
export OMP_NUM_THREADS=$(lscpu | awk '/CPU\(s\):/{printf("%d\n",$2)}' | grep -v 0)
./stream >> stream.out
done
# 提取 CSV 格式结果
cat stream.out | grep -E "Copy:|Scale:|Add:|Triad:" | awk '/:/{gsub(/:/,"",$1); print $1","$2","$3","$4","$5}' > stream_results.csv
3. Intel MLC 内存测试
Intel Memory Latency Checker(MLC)可同时测量内存延迟矩阵和带宽矩阵:
# 延迟测试 — 输出跨核心/跨 NUMA 的延迟矩阵
./mlc --latency_matrix
# 带宽测试 — 输出各 NUMA 节点间的带宽
./mlc --bandwidth_matrix
--latency_matrix— 从每个核心访问本地/远端内存的延迟(ns)--bandwidth_matrix— 从每个核心读写本地/远端内存的带宽(MB/s)- 适用场景:多路服务器 NUMA 拓扑分析,验证跨 socket 访问性能
4. 内存压力 / 稳定性测试
stress
通用的系统压力测试工具:
# 内存压力:50 个 vm 进程,每个分配 5G,挂起 100 秒,测试 12 小时
stress -i 4 --vm 50 --vm-bytes 5G --vm-hang 100 --timeout 43200s
# 按剩余内存的 1/8 分配 8G 每个,测试 12 小时
date && stress -m $(free -g | awk '/Mem/{printf("%.0f\n",$4/8)}') --vm-bytes 8G --vm-hang 5 -t 43200s
-m N/--vm N— 并发 vm 进程数--vm-bytes N— 每个进程分配的内存大小--vm-hang N— 分配后挂起秒数--timeout— 测试持续时间
memtester
用户态内存稳定性测试,检测内存故障:
# 下载编译
curl -Ol http://pyropus.ca/software/memtester/old-versions/memtester-4.5.0.tar.gz
tar -zxf memtester-4.5.0.tar.gz
cd memtester-4.5.0
make
# 测试 32G 内存,执行 1 遍
date && ./memtester 32G 1 && date
# 按剩余内存的 80% 测试
date && ./memtester $(free -m | awk '/Mem/{printf("%.0f\n",$4*0.8)}') 1 && date
参数: memtester <内存大小> <迭代次数>
结果解读:测试通过无输出即为 PASS。如果检测到故障会输出 "FAIL" 及具体出错地址。
mbw
内存带宽快速评估:
mbw -q -n 3 4096
-q— 精简输出,隐藏日志-n 3— 运行 3 次4096— 测试内存大小(MB),建议用剩余内存的一半- 结果解读:关注 AVG(平均值),三次值对应内存拷贝(MEMCPY)、字符串拷贝(DUMB)、内存块拷贝(MCBLOCK)带宽
ramspeed
对整数/浮点内存读写带宽的细分测试:
# 整型写
./ramsmp -b 1
# 整型读
./ramsmp -b 2
# 浮点写
./ramsmp -b 4
# 浮点读
./ramsmp -b 5
5. lmbench 内存微基准
lmbench 的 lat_mem_rd 测试内存延迟(ns)随工作集大小的变化曲线:
# 运行全部 lmbench 测试
make results
make see
内存延迟结果通常以 ns 呈现,数值越小越好。当工作集超过 L3 缓存大小时,延迟显著上升(L3 hit 约 10-30 ns → 内存访问约 60-120 ns)。
关键指标对比
| 工具 | 测试类型 | 主要关注指标 | 适用场景 |
|---|---|---|---|
| STREAM | 带宽 | Copy/Scale/Add/Triad (MB/s) | 标准内存带宽验收 |
| MLC | 延迟+带宽 | latency_matrix, bandwidth_matrix | NUMA 拓扑分析 |
| memtester | 稳定性测试 | PASS/FAIL + 地址 | 内存故障排查 |
| stress | 压力负载 | 是否 OOM/crash | 系统稳定性验证 |
| mbw | 快速带宽 | MEMCPY/DUMB/MCBLOCK (MB/s) | 快速粗测 |
| ramspeed | 读写细分 | INT/FLOAT 读写带宽 | 分类性能分析 |
| lmbench | 微基准 | 延迟 (ns) | 缓存/内存层级分析 |
出链
- cpu-testing — CPU 性能与缓存测试,与内存子系统协同分析
- disk-storage-testing — 磁盘 I/O 测试中清理缓存的预备操作