Linux Page Cache 导致视频解码第一次慢、第二次快的原因分析与缓存清理方法
本人工作中遇到的实际问题,结合大模型分析后找到了原因
本文在CHATGPT帮助下完成
1. 问题背景
在使用 PyNvVideoCodec 做 GPU 视频解码测试时,发现一个非常奇怪的现象:
同一个视频:
第一次运行:
PyNvVideoCodec decode: 10s第二次运行:
PyNvVideoCodec decode: 2s代码、GPU、Docker 环境完全没有变化。
初步怀疑:
- PyNvVideoCodec 第一次初始化慢?
- NVDEC 有缓存?
- Qwen 模型加载影响?
- Docker 容器导致?
- GPU 驱动问题?
经过多组实验,最终定位:
真正影响性能的是 Linux Page Cache(文件缓存),而不是 GPU 解码本身。
2. Linux Page Cache 是什么?
Linux 不会每次读取文件都直接访问磁盘。
当程序读取文件:
程序 | | read() ↓ Linux Kernel | ↓ 磁盘第一次读取:
磁盘 ↓ Page Cache ↓ 程序Linux 会把读取的数据缓存在内存中。
第二次读取:
程序 | ↓ Page Cache | ↓ 直接返回不需要再次访问磁盘。
因此:
第一次:
磁盘 IO + 解码第二次:
内存读取 + 解码速度可能产生明显差异。
3. 为什么 Docker 重启后缓存还存在?
很多人会误以为:
Docker 容器退出后,缓存应该消失。
实际上不是。
Page Cache 属于:
Linux Kernel不是:
Docker Container例如:
第一次:
Docker A 读取 video.mp4 ↓ Linux Page Cache然后:
Docker A退出但是:
Linux Kernel仍然运行。
再次:
Docker B 读取同一个 video.mp4仍然可以命中之前的 Page Cache。
所以:
不同 docker run 之间可以共享文件缓存。
4. 如何查看一个文件是否已经缓存?
推荐工具:
vmtouch
安装:
Ubuntu:
sudoaptinstallvmtouch查看文件:
vmtouch video.mp4输出:
Files: 1 Directories: 0 Resident Pages: 121973/121973 476M/476M 100% Elapsed: 0.000458 secondsResident Pages 怎么理解?
Linux 使用 Page 管理内存。
通常:
1 Page = 4096 Bytes例如:
视频:
476MB大约:
476MB / 4KB ≈121973 Pages输出:
Resident Pages: 121973 / 121973表示:
总页数: 121973 已经在内存中的页: 121973也就是:
100%代表:
整个视频已经进入 Linux Page Cache。
如果:
Resident Pages: 50000 / 121973 40%说明:
只有 40% 的视频数据已经缓存。
5. 查看目录缓存情况
查看整个目录:
vmtouch /data/videos递归查看:
vmtouch-r/data/videos例如:
Files: 100 Directories: 1 Resident Pages: 500000/800000 62%表示:
目录下所有文件:
约 62% 已经在内存缓存。
6. 如何清理 Linux Page Cache?
性能测试时,经常需要模拟:
第一次访问文件(冷缓存)
可以使用:
方法一:清理整个系统缓存
执行:
sudosh-c"sync && echo 3 > /proc/sys/vm/drop_caches"解释:
sync
把脏数据写回磁盘:
RAM ↓ 磁盘避免数据丢失。
echo 3
含义:
1: 清理 Page Cache 2: 清理 inode/dentry cache 3: 两者都清理一般测试使用:
3清理后验证:
vmtouch video.mp4应该:
之前:
Resident Pages: 121973/121973 100%变成:
Resident Pages: 0/121973 0%7. 更推荐:只清理指定文件缓存
如果只是测试某个视频,不建议清理整个系统缓存。
使用:
sudovmtouch-evideo.mp4其中:
-e = evict表示:
将该文件从 Page Cache 中移除。
验证:
vmtouch video.mp4看到:
0%即可。
8. 一个完整的视频解码测试流程
例如测试 PyNvVideoCodec:
第一步:清缓存
sudovmtouch-evideo.mp4确认:
vmtouch video.mp4结果:
0%第二步:运行解码
第一次:
decoder[i] 10s第三步:查看缓存
vmtouch video.mp4结果:
100%说明:
视频已经进入 Page Cache。
第四步:再次运行
第二次:
decoder[i] 2s原因:
Page Cache命中9. top/free 能看到这些缓存吗?
很多人会使用:
top查看内存。
注意:
Page Cache 不属于某个进程。
所以:
top RES不会包含文件缓存。
查看:
free-h可以看到:
buff/cache但这个包含:
- Page Cache
- inode cache
- slab 等
不是精确的文件缓存。
如果想知道:
某个视频是否缓存:
使用:
vmtouch更准确。
10. 对视频处理系统的启示
对于视频分析任务:
例如:
NAS | 复制 | 本地SSD | PyNvVideoCodec | Qwen | MediaPipe推荐:
不要直接从网络文件系统做随机帧读取。
原因:
视频随机访问:
decoder[idx]会频繁触发:
seek read decode网络存储延迟会直接影响解码时间。
更稳定的架构:
NAS作为存储 ↓ 复制到本地SSD ↓ GPU解码这样性能更加稳定,也方便测试。
总结
Linux Page Cache 是导致:
第一次读取慢 第二次读取快的主要原因之一。
关键命令:
查看文件缓存:
vmtouchfile清理单个文件:
sudovmtouch-efile清理系统缓存:
sudosh-c"sync && echo 3 > /proc/sys/vm/drop_caches"对于视频解码性能测试,必须区分:
- 磁盘/NAS读取性能
- Page Cache命中
- GPU解码性能
否则容易误判:
“GPU解码慢”
实际上可能只是:
“第一次读取文件慢”。
