为什么 ffmpeg 的体积会这么大?多复杂的算法编译后也不会有几十 MB 吧?

2023-03-25 18:49:12 +08:00
 LLaMA
9934 次点击
所在节点    FFmpeg
47 条回复
talkischeap567
2023-03-26 05:10:08 +08:00
反串?
talkischeap567
2023-03-26 05:12:22 +08:00
为什么 windows 的体积会这么大?多复杂的系统编译后也不会有几十个 G 吧?
为什么 ios 的体积会这么大?多复杂的手机系统编译后也不会有 10 个 G 吧?
billccn
2023-03-26 05:18:12 +08:00
用静态语言编写的追求高性能的代码编译结果大是很正常的,因为最基本的优化方向就是针对不同的情况有专门的代码。比如:

* 针对不同的指令集(各种版本的 SIMD)分别生成代码
* 针对某些数据类型进行特定的优化
* 依赖查表而不是运算
* 循环 unrolling
* 为了减少跳转而把越来越多的函数 inline
* 利用条件运算减少分支

这些叠加在一起还会形成 combinatorial explosion.

说笼统一点就是空间换时间的思路。
msg7086
2023-03-26 07:10:04 +08:00
但凡你知道很多代码为不同指令集分别做了优化并且运行时自动选择最优路径导致编译出来的二进制体积成倍增长也不至于嫌他大(

一般人用 ffmpeg 完全可以裁剪出自己需要的功能。比如我之前发布的一个软件,用到了 m2ts 解包功能,ffmpeg 裁剪到只需要支持 file protocol 和 mpegts demuxer ,出来只有几百 KB 。
msg7086
2023-03-26 07:15:17 +08:00
运行一下下面这些命令再看看你觉得多大容量比较合适。

ffmpeg -codecs
ffmpeg -formats
ffmpeg -muxers
ffmpeg -demuxers
ffmpeg -protocols
ffmpeg -filters
msg7086
2023-03-26 07:19:23 +08:00
另外再说说规模问题。

ffmpeg 里用到的 x265 ,他里面源码中最核心的那些汇编文件,光 x86 指令集,就有 20 多万行。这没算其他的指令集,没算外围的那些代码,没算 ffmpeg 里其他的大项目。就这一个目录就 20 万行。

不要小看大型项目的规模啊……
whi147
2023-03-26 08:00:58 +08:00
自己裁剪,我裁剪后就两三兆
paranoiagu
2023-03-26 08:40:04 +08:00
应该是静态编译才这么大吧。
secondwtq
2023-03-26 09:29:40 +08:00
这是个有趣的问题。实际上如果只是想把一个东西做得体积很大很简单,一个真实的故事:
一个算法有 2 个较为固定的参数,每个参数有 5 种可能性,那么如果我把这些参数静态编译进去就是 25 种可能性,如果再考虑到在 5 种不同硬件上的组合,那就是 125 种。如果假设每种的代码有 1KB 大,再有三四十个类似的算法,光这玩意就能整出 4MB 来。

类似地,如果工程中涉及到根据外部数据文件生成可执行代码,如 RPC 协议通信等,随着数据越来越多,附加的代码也会越来越多。

另外,编译器优化也可能导致代码体积的指数增长,常见地例如:
* 如果一个函数里面出现了对其他函数的多次独立调用,而这些函数又被 inline 。该函数实际生成的代码会包含子函数代码的多个拷贝。如果多个函数 inline 了同一个函数,该子函数代码会被在不同函数中多次拷贝。
* 如果一个函数被多次调用,并且调用时使用了常量参数,该函数的代码可能会被拷贝多份,并将常量参数代入其中单独优化。
* 循环的 unroll 会将循环体代码拷贝多份(虽然一般会有一定的长度限制)。
* 循环的向量化会将循环体代码拷贝多份(不同于 unroll ,这个是向量化逻辑所必须的,因此一般不会限制)。

我这有个对比的例子是 GTK3 。目前我这的 GTK3 包一共 49MB ,不过里面有一堆 GTK 元数据和 locale 之类的东西。只看最关键的 libgtk-3.so ,这玩意一共 7.8 MB ,其中 .text 大概有 3.7MB ,由 500 多个 .o 链接而成,这些 .o 的 .text 大小相加和 libgtk-3.so 的 .text 差不多。.text 最大的前 10% 的 .o ,.text 大小加起来大概 1.6MB 。这些 .o 对应的源码大小加起来大概 7.6MB 。总的源码大小是 17MB (只算 .c ,不算 header )。把 .o 的 .text 大小,和对应 .c 文件的大小画个图,可以很清楚地发现 .c 文件的大小大概是 .text 大小的 4-6 倍,平均值是 5 倍左右。

ffmpeg 包一共 37MB ,其中最大的是 libavcodec.so ,15MB 。.text 有 10MB 。大概有 1100 个 .o (我去除了一部分直接汇编出的 .o ,这些 .o 的 .text 加起来大概 1MB )。.text 最大的前 10% 的 .o ,.text 大小加起来大概 5.3MB 。这些 .o 对应的源码大小加起来大概 5.6MB ,总的源码大小是 19MB 。部分 .o 依然满足 4-6 倍的规律,但是整体的分布分散了许多。很多头部的 .o ,其 .c 文件大小是 .text 文件大小的两倍,一倍,甚至零点几倍。总的来说相比 GTK3 ,ffmpeg 编译生成的 .text 要更大。
进一步研究源码发现:
* libavcodec 源码中有很多以 _template.c 结尾的文件,加起来 1MB 左右,这些文件并不会直接编译出 .o (因此并不会计算在上面的 .c 大小上),而主要是被以不同的参数(如位深度)等多次 include 到不同的 .c 中,其实类似于模拟 C++ 的 non-type template parameter 。这些文件中的代码自然也会被拷贝多份。
* 部分源码大量使用了定义宏再多次以不同参数使用宏的技巧,这个还是类似于 non-type template parameter ,同样会导致同样的代码被拷贝多份。
* .o 中的代码存在大量 inline 的痕迹。也出现了一些 constprop 函数。源码中大量函数标记了 always_inline 。

#14 的链接中指出使用 --enable-small 选项(即指示编译器优先优化代码体积)可以数倍降低 libavcodec.so 的大小。暗示编译器优化是巨大体积的重要因素。不过我实测的效果并没有那么吼,.text 大概降低了 40% 左右。相对地,libgtk-3.so 降低了不到 20%。不过确实可以看到很多的 .o 文件 .text 大小成倍地缩小。GTK3 则鲜有缩小超过 30% 的 .o 。
liberize
2023-03-26 09:33:10 +08:00
chrome 一个 dll 已经超过 200MB 了
sl0000
2023-03-26 10:26:52 +08:00
一个模板函数就能编译出几十个 G 的执行文件, 和代码行数有关系吗?
Kisesy
2023-03-26 13:38:53 +08:00
可能是因为高度优化,导致内联过多,或者循环展开等原因吧
bruce0
2023-03-26 14:28:13 +08:00
pika,一个基于 rocksdb 开发的类似 Redis 的数据库, 以前用手写 MakeFile 组织代码编译,最近开始使用 cmake 重新组织代码编译. 除了几个系统库全部使用静态链接. 在下不才,cmake 默认编译方式那部分是我写的
如果使用 `DCMAKE_BUILD_TYPE=Debug`,这样编译出来的是带调试符号的,最终的可执行文件是 230M,
如果使用 `DCMAKE_BUILD_TYPE=Release` pika 部分代码使用 -O2 优化,依赖库都使用 release 编译, 去掉调试信息 最终的可执行文件是 25M

最后说一下我的结论啊, 编译时加不加调试信息,对最后的二进制体积影响非常大; 有时候可能就是一堆逻辑,没有任何 gui,图片等等资源,编译出来就是几十 M 了,
sharpy
2023-03-26 14:40:57 +08:00
一般自己裁剪吧,disable-everything ,然后看着需求开
fy
2023-03-26 15:35:52 +08:00
+1 同样疑问,不知道 github 上有没有公开的带 action 的裁剪编译,只需要少数几个编码转换到 silk
SekiBetu
2023-03-26 18:07:35 +08:00
代码体积就有好几个 G 了,编译算是削减了体积
herozzm
2023-03-26 18:09:20 +08:00
能到这么小很不容易了,它能转码几乎所有视频编码的视频
009694
2023-03-26 20:07:51 +08:00
楼主只是疑问为什么 ffmpeg 编译出来体积怎么这么大。 为啥这么多人回复这么充满攻击性和蔑视? 甚至还有 “嫌大你自己写” 这种毫无帮助甚至涉嫌引战的回复
ch2
2023-03-26 22:33:09 +08:00
因为去掉简单,但是你永远不知道哪个人因为你去掉了什么他的代码就运行不起来,所以就维持在一个兼容性较好的子集里
yolee599
2023-03-27 09:08:40 +08:00
@009694 主要是最后面一句,多复杂的算法编译出来都不会有几十 MB ?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/927148

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX