llcbench 实战:用 tar.gz 源码包做 Linux 缓存与延迟基准测试
2026/9/9 13:20:36 网站建设 项目流程

简介:LLCbench(Low-Level Characterization Benchmarks)是一套面向底层硬件性能评估的基准测试工具,集成MPBench、CacheBench、BLASBench三类测试方法,此处聚焦其中的CacheBench部分,用于Linux环境下缓存性能的量化测试与分析。该工具通过精心设计的内存访问模式,帮助量化缓存层次结构对程序性能的影响,适合系统性能工程师、运维人员及高校研究者进行硬件选型与调优。压缩包共81个文件,大小83KB,主要包含C源码、Makefile构建脚本、shell脚本、Gnuplot绘图配置(gp)以及html/readme/tex说明文档等,覆盖测试程序的编译、运行、结果可视化与配置说明全流程。当前已有869人学习下载,可用于快速搭建缓存基准测试环境。借助其中的CacheBench测试程序与绘图脚本,可了解缓存测试的逻辑与参数配置,快速生成性能图表,并参考文档开展不同处理器/内存架构下的缓存命中率、带宽等指标对比实验,为系统性能优化和硬件评估提供实测数据支撑。 我最早拿到llcbench.tar.gz这个包,是在做 Linux 内核性能回归测试的时候。当时团队要验证一组调度器补丁会不会引入延迟抖动,翻社区资料时几乎每个讨论帖都会提到llcbench,搜索结果里出现频率最高的就是这同一个压缩包文件名。解压、编译、跑完一轮之后,我才意识到这个看似古老的 tarball 里装的东西,比我想象中要实用得多。

llcbench是一套面向 Linux 底层缓存、内存带宽和系统调用往返延迟的微型基准测试集合,主要用来做“某个改动前后到底有没有变慢”这种对比实验。它不像fio那样专门测磁盘吞吐,也不像lmbench那样追求全面,它更聚焦在 CPU 缓存层级、内存拷贝、进程间通信这些偏底层的路径上。适合三类人看:一是内核开发者,二是做性能优化的应用工程师,三是对 Linux 底层机制好奇、想亲手折腾 benchmark 的爱好者。而我下面的内容,就是基于一次完整实操过程整理的笔记,包括解压、编译、运行、读结果,以及踩过的坑。

1. 拿到压缩包后,先搞清楚它到底是什么

1.1 llcbench 的核心定位

在 Linux 性能测试圈子里,llcbench不是那种一跑就给你一个“综合分数”的工具。它的全称可以理解为LLC (Last-Level Cache) Benchmark 系列,由 IBM Linux 技术中心的工程师维护,最初是为了给内核补丁做性能回归扫描而设计的。它关注的不是“多快”,而是“有没有引入额外延迟”。

包里的工具覆盖了几个层面:

  • cachebench:针对 cache 命中/未命中的延迟和带宽做测试,找出跨核访问、伪共享这类问题。
  • pass1/pass2:做内存与缓存吞吐量的分级扫描,数据量大时可以观察到不同 cache 层级的分界点。
  • sbrc:测试系统调用级别的往返延迟,用于感受 syscall 路径上的开销变化。
  • bw_mem:内存带宽测试,检验拷贝、赋值、读写在内存子系统上的真实带宽。
  • strem:类似 STREAM 的简化版内存带宽基准,用于大规模内存带宽验证。

另一个很关键的点是:这个包不是设计来给你测“绝对性能”的,而是给你做“前后对比”的。同一台机器,用同样的参数,在内核基线版本和打补丁版本之间跑两轮,差值才是有意义的指标。这一点直接决定了后面你该用什么方式去运行、怎么解读输出。

1.2 为什么这种工具会以 tar.gz 形态分发

现在很多人习惯了git clone,看到.tar.gz甚至会觉得有点古老。但像llcbench这种工具的源码包,以 tar.gz 形式分发是有实际原因的:

  • 它依赖的代码文件数量不多,体积也小,归档后就是一个干净的源码树,能保证拿到手的就是发布时刻的完整快照,不依赖远程仓库的可访问性。
  • 免去了安装额外版本管理工具的步骤。在最小化服务器环境里,targzip是所有发型版基本都会安装的,零额外依赖。
  • 便于做发布校验。压缩包里往往自带READMEMakefile,版本冲突、文件变更都有记录,对内核开发这种需要严格复现的场景来说,源码快照比“最新 master 代码”更靠谱。

所以不要嫌弃.tar.gz土,它其实是最稳妥的分发方式。后面我在内网环境、离线环境里也验证过,所有依赖都在包内,只要系统基础工具链没问题,就能编译运行。

2. 解压与包内结构:动手前先读 README

2.1 tar.gz 解压命令与背后的细节

对刚接触 Linux 的人来说,解压 tar.gz 可能直接搜“tar.gz 解压命令”,然后背一条命令就完事。但实际做性能测试的人,通常会多考虑一层:解压到哪、权限对不对、内容会不会覆盖现有文件。

最基础也最常用的命令是:

tar -zxvf llcbench.tar.gz

各参数含义:

  • -z:通过 gzip 解压。.tar.gz本质是先用tar归档,再用gzip压缩。所以不加-ztar -xvf会对纯.tar文件有效,对.tar.gz则会报“gzip: compressed data not read”之类的错误。
  • -x:执行释放(extract)操作。
  • -v:显示释放的文件清单。在解压陌生包时建议保留,能直观看到文件结构和是否有异常文件。
  • -f:指定要操作的归档文件名。-f必须放在后面紧跟着文件名,这是初学者最容易踩的坑:tar -xvfz llcbench.tar.gz或者tar -fxv这样的顺序都会出问题。

如果你是第一次解压陌生项目,更稳妥的方式是:

tar -ztvf llcbench.tar.gz

-t表示列出内容而不解压。通过这个命令可以提前看到包内目录结构,确认它不是要往当前目录里撒一堆文件,而是自带一个顶层目录llcbench/。如果包里的第一层就是零散文件,那你解压时必须先手动建一个子目录再进去,避免污染当前目录。

2.2 包内结构解读

解压完之后,正常情况会出现一个llcbench/目录。我这次拿到的小版本目录结构大致是这样:

llcbench/ ├── README ├── COPYING ├── Makefile ├── src/ │ ├── Makefile │ ├── cachebench/ │ ├── sbrc/ │ ├── pass1/ │ └── ... └── scripts/

我的建议是:先读 README,再看 Makefile,最后才碰源码。这个包里的 README 不啰嗦,但会明确写出各个测试工具的依赖、编译顺序、默认运行参数。比如 README 里会提示cachebench需要以多进程方式跑测跨核延迟,如果你忽略了就直接单进程默认跑,那么结果反映的只是单核 cache 的延迟,根本测不到跨核问题,整个实验白做。

在正式编译前,我还习惯确认一下包内有没有奇怪的路径异常。比如:

find llcbench -type f -name "*.c" | wc -l

这是一个简单的“样本检查”,能让你对源码规模有个初步认识,也顺便验证解压过程没有缺文件。如果数量太少甚至为零,那可能是下载的包不完整,应该重新校验。

3. 编译与环境排错:看似简单,坑其实不少

3.1 官方 Makefile 编译流程

llcbench的编译不像新式项目有configure脚本,也没有 CMake,它就是一个纯粹的 make 工程。进入源码根目录后,直接:

make

正常情况下 make 会遍历所有子目录,把cachebenchsbrcbw_mem等工具分别编译出来,最终可执行文件会落在src/bin/或者各自子目录里,具体看 Makefile 怎么定义。

编译过程中我遇到的最典型问题是64 位平台下的隐式声明告警。这个包的历史有点老了,部分源码里没有显式#include <unistd.h>,在现代 GCC 默认版本下会疯狂刷 warnings,尤其集中在pass1strem这两个小工具上。第一次遇到时我差点以为编译失败了,后来确认只要没有 error 级输出,最终可执行文件正常生成,就说明能用。如果编译器把-Werror打开了,那才是真问题,需要手动给对应 Makefile 去掉-Werror或者修改对应的 include。

3.2 依赖关系的一个小插曲

有人拿到llcbench.tar.gz时,会把它和e2fsprogs 1.46.6 tar.gz这类文件搞混。这里澄清一下:e2fsprogs是 ext 系列文件系统工具组,负责mkfs.ext4fscktune2fs这些命令;llcbench是性能基准测试,两者没有任何编译依赖关系。但为什么这两个热词经常被放在一起搜?我猜是因为它们都是 “tar.gz 的 Linux 老牌源码包”这个标签下的常客。

不过在跑测试之前,有一个间接相关的点需要确认:如果你打算在 ext4 文件系统上做内存/缓存类测试,不需要 e2fsprogs 做什么,但如果你长期接触文件系统、磁盘调试,e2fsprogs的版本会影响你对测试环境的判断。比如我用fsck检查测试分区时,文件系统特性版本和工具版本不匹配会报 mismatch 警告,这种环境问题如果没排除,最后 benchmark 数据出现诡异波动,第一个该怀疑的就是底层文件系统状态,而不是内核补丁本身。我做性能对比实验时有个习惯:跑测试前先执行一次fsck并记录工具版本,这不是 llcbench 的依赖,但它是保证结果可信度的前置条件。

另外要注意编译期依赖:llcbench大多只用到 libc,不需要额外装第三方库。但需要确认系统具备完整的构建工具链。检查方式:

gcc --version make --version

如果是最小化 docker 或精简系统,很可能连 make 都没有。此时 debian/ubuntu 系:

apt-get install build-essential

Red Hat/CentOS 系:

yum install gcc make

这一步别跳过。我见过多次编译报 “make: command not found”,排查一圈才发现是基础工具链缺失。

4. 运行基准测试,结果该怎么看

4.1 cachebench 参数选型

编译完成之后,我习惯先跑一个最容易出问题、功能也最有代表性的工具:cachebench。它的参数不复杂,常见的有:

./cachebench -p 4 -w 100 -r 0 -d 100
  • -p:并行进程/线程数。用于跨核并发测试,我一般设为要测试的物理核数,比如 4 核就传 4。
  • -w:写操作占比。100 表示全写,0 表示全读。
  • -r:读操作占比。和-w配合,-w 100 -r 0是全写场景,-w 0 -r 100是全读场景。
  • -d:持续时间,单位通常是秒。因为 cachebench 会反复遍历特定大小的内存块,持续时间太短可能采样不足。

如果你不知道填多少,可以先跑一个内存块大小从 1KB 到 64MB 的扫描模式。一些版本支持-c指定 cache 大小或者通过-s指定最大测试内存块。从经验上看,内存块大小至少要覆盖到 L2 和 L3 之间,才有区分度。如果全部数据都塞进 L2 了,测出来的延迟基本就是 L2 命中延迟,而对内核补丁引入的跨核开销不敏感。

命令示例:

./cachebench -p 4 -w 0 -r 100 -c 64 -d 120

这里-c 64表示测试内存块最大 64MB,能覆盖常见 CPU 的 L3 容量,能看到 cache 容量边界处的延迟“断崖”。如果只测单个固定大小,例如:

./cachebench -p 4 -w 50 -r 50 -s 8 -d 60

-s 8表示固定使用 8MB 块,读写各 50%。适合快速验证补丁是否对某一大小的内存访问有影响。

4.2 理解输出数字

cachebench的输出通常是一张表格,列出不同进程数、不同内存块大小下的延迟数据。初看时很容易懵,因为数字种类太多。我个人的习惯是只关注这几列指标:

指标关注点
latency(纳秒)单次访问的往返延迟,越小越好
bandwidth(MB/s 或 GB/s)吞吐量,越高越好
L2 / L3 hit ratio命中率,辅助判断测试块是否落在对应缓存层级
cross-thread latency跨线程通信往返延迟,重点观察

做对比实验时,重点不是看某一个数值有多好看,而是看基线版本和测试版本之间的差值。比如我这次跑调度器补丁验证,基线版本cachebench -p 4跨线程延迟是 420ns,打完补丁变成 430ns,虽然只多了 10ns,但因为重复 20 轮稳定复现,就可以判定补丁在跨核通信路径上引入了额外开销。反之,如果今天 400ns、明天 410ns、后天 398ns,波动比差值还大,那补丁根本背不了这个锅。

一个非常实用的技巧是:先把同一环境重复跑 5 次,计算标准差。如果标准差大于你要验证的性能差值,那就得先提高测试次数或者锁定 CPU 频率(cpupower frequency-set -g performance),否则数值没有说服力。

4.3 跑一轮完整的回归对比

实践中我会跑一个最小但完整的流程:

  1. 记录内核版本、CPU 型号、memory 大小、文件系统类型。
  2. 当前内核不应用补丁,编译运行 cachebench、pass1、bw_mem,各 3 次,记录均值和标准差。
  3. 应用补丁,重新编译内核并重启。
  4. 用相同的参数再跑一遍同样的 3 个工具。
  5. 对比结果。

这个流程听起来很繁琐,但内核性能验证本来就是这样。llcbench的定位就是给这个流程提供“小而精确”的指标。它不负责告诉你“系统好不好”,只负责告诉你“变了没有”,而后者恰恰是补丁合入前最需要的事实依据。

5. 常见问题与排查技巧实录

5.1 我踩过的坑和解决方案

这里把实操中最常见的问题整理成一张速查表,以后遇到可以少走弯路:

现象原因解决方案
tar -xvf llcbench.tar.gzgzip: compressed data not read忘记加-z参数改用tar -zxvf
解压后文件散落当前目录包内无顶层目录或有多个顶层项tar -ztvf查看结构,提前建目录再解压
make 过程大量implicit declaration告警老源码对现代 GCC 兼容性一般只要没有 error,可忽略;或手动补 include
多个测试工具编译失败子目录 Makefile 依赖了已失效的旧路径重新检查 root Makefile,单独进入子目录逐一编译
运行时提示cannot open /dev/mem某些工具需要 root 权限sudo运行,或配置能力位
结果波动极大CPU 频率调整、其他进程干扰锁定性能和 CPU 亲和性:taskset -c 0-3 ./cachebench ...
找不到bw_mem等二进制可执行文件路径不在当前目录确认src/bin/src/工具名/bin/,用find . -type f -perm -111查找

5.2 关于 tar.gz 本身的两个细节提醒

第一个细节:检查完整性llcbench.tar.gz在网上下载后,可能出现下载中断但文件名却完整的情况。解压时会报unexpected end of file,这比解压后编译失败更好排查。建议下载完成后执行:

gzip -t llcbench.tar.gz

如果输出llcbench.tar.gz: ok,说明 gzip 压缩数据完整。这是一个非常轻量但非常有效的体检方式。

第二个细节:解压路径权限。如果放到/opt/usr/local/src这类系统目录下,要用 root 解压;解压后源码目录如果允许普通用户编译,最好chown -R改成自己的用户,避免编译产生的临时文件无法写入。当然如果你只是在个人目录下测试,就没有这个问题。

最后再分享一个我的实际习惯:拿到任何一个 tar.gz 源码包,永远先解压到一个临时目录,跑diff -rq对比两次解压结果,确认文件完整;然后readelf -d查看动态库依赖;最后再按 README 走编译。这套流程帮我避开了不少“压缩包没下全”“解压工具版本不一致”之类的隐形坑。llcbench本身并不复杂,但它的运行环境往往是你生产环境的同款内核,把环境打理干净,测试数据才有价值。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询