转码慢的根源:CPU瓶颈 vs IO瓶颈,为什么你的CPU跑不满?

做转码优化的第一件事,不是调参数,也不是换库。

而是搞清楚——你的程序到底卡在哪里。

我见过太多团队,上来就怼着FFmpeg的preset调了一整天,结果速度没变。为什么?因为他们根本没找到真正的瓶颈。转码慢,无非两个原因:要么CPU在拼命干活但干不过来,要么CPU在闲着等数据。前者叫CPU瓶颈,后者叫IO瓶颈。

说白了,你得先知道敌人是谁,才能选武器。

先看一个真实案例

去年我帮一家视频平台做优化。他们的转码集群有32核的机器,但跑转码任务时,CPU利用率只有15%。

15%!

你想想看,32核的机器,几乎都在空转。他们以为是代码效率低,换了好几个编码器,都没用。

我一查,问题出在输入源上。他们从NAS读文件,网络带宽只有100Mbps。一个4K视频的码率是50Mbps,但转码过程中需要反复seek读取,实际吞吐量连20Mbps都不到。CPU大部分时间都在等数据从网络传过来。

这就是典型的IO瓶颈。

核心判断标准:

  • CPU利用率 > 90%,但转码速度慢 → CPU瓶颈
  • CPU利用率 < 50%,转码速度慢 → IO瓶颈
  • CPU利用率在50%-90%之间波动 → 混合瓶颈,需要进一步分析

CPU瓶颈:你的CPU真的在全力工作吗?

很多人以为转码就是CPU在算算算。其实不是。

转码管线里,解码、滤镜、编码,每个环节对CPU的消耗都不一样。我习惯用perf top或者htop先看一眼,哪个线程在吃CPU。

# 查看转码进程的CPU占用分布
$ perf top -p $(pgrep ffmpeg)

# 或者用pidstat看每个线程
$ pidstat -t -p $(pgrep ffmpeg) 1

如果发现解码线程CPU跑满,但编码线程空闲,说明解码器成了瓶颈。反过来也一样。

嗯,这里要注意:不是所有编码器都能充分利用多核。比如libx264的ultrafast preset,单核就能跑满;但换成veryslow,它能吃满所有核心。你选错了preset,CPU再多核也白搭。

编码器 preset CPU核心利用率 典型场景
libx264 ultrafast 1-2核 实时推流
libx264 medium 4-8核 常规转码
libx264 veryslow 16核+ 离线压片
libx265 medium 8-16核 HEVC转码
NVENC p1-p7 1-2核 GPU加速

我的经验:如果你用软件编码,先试试把preset调慢一档。如果CPU利用率上升了,说明之前确实是CPU没跑满。如果没变化,那问题就不在编码器上。

IO瓶颈:CPU在等什么?

IO瓶颈比CPU瓶颈更隐蔽。因为CPU利用率低,很多人第一反应是“机器性能不够”,然后加钱升级CPU。结果钱花了,速度没变。

我曾经踩过这个坑。有一次做批量转码,从HDFS读文件,CPU利用率一直上不去。我以为是解码器的问题,换了三个解码库,都没用。最后用iostat一看,磁盘等待时间(await)超过200ms。

说白了,CPU在等磁盘把数据送过来。

# 查看磁盘IO等待
$ iostat -x 1

# 重点关注:
# %util - 磁盘利用率
# await - IO等待时间(ms)
# rkB/s, wkB/s - 读写吞吐量

IO瓶颈的常见原因:

  • 磁盘太慢:HDD vs SSD,顺序读写 vs 随机读写,差距巨大
  • 网络带宽不足:从远程存储读文件,网络成了水管瓶颈
  • 文件系统开销:小文件太多,元数据操作拖慢整体
  • 并发读写冲突:多个转码任务抢同一个磁盘

注意:别只看磁盘利用率(%util)。有时候%util只有30%,但await已经很高了。这说明磁盘在同时处理多个请求,每个请求都在排队。真正的瓶颈是IOPS,不是带宽。

如何快速定位瓶颈?

我个人的习惯是三步走:

  1. 看CPU利用率:top或htop,确认CPU是不是在忙
  2. 看IO状态:iostat -x 1,检查磁盘等待时间
  3. 看网络流量:nload或iftop,确认网络有没有打满

这三步走完,瓶颈基本就现形了。

举个例子:

  • CPU 95%,磁盘await 5ms → CPU瓶颈,优化编码参数或换硬件
  • CPU 20%,磁盘await 300ms → IO瓶颈,换SSD或加缓存
  • CPU 60%,磁盘await 50ms,网络打满 → 混合瓶颈,先解决网络

一张图看懂转码瓶颈

下面这张图,是我做性能分析时常用的框架。它帮你把转码管线拆开,每个环节的瓶颈一目了然。

转码性能瓶颈分析框架 输入源 本地磁盘 / 网络 / 对象存储 解码器 CPU解码 / 硬解 滤镜处理 缩放 / 裁剪 / 水印 编码器 软件编码 / 硬件编码 输出存储 本地磁盘 / 云存储 / CDN 各环节瓶颈特征 输入源瓶颈: • 磁盘await > 100ms → 换SSD或增加缓存 • 网络吞吐量 < 视频码率 → 升级带宽或本地缓存 解码/编码瓶颈: • 单线程CPU跑满 → 换多线程解码器或硬解 • 编码preset太慢 → 调快preset或换硬件编码 输出存储瓶颈: • 写入速度跟不上编码速度 → 换高性能存储

总结一下

转码慢,别急着调参数。先看CPU利用率。

CPU跑满了,那是计算瓶颈,优化编码器、换硬件、上GPU。

CPU没跑满,那是IO瓶颈,查磁盘、查网络、查文件系统。

我见过太多人在这上面浪费时间。你想想看,如果瓶颈在磁盘,你花三天调编码参数,能快吗?

嗯,先把敌人找出来,再动手。