二进制库瘦身 以及 Flutter 裁剪

Flutter Engine 调优系列 (二) – 二进制库瘦身 以及 Flutter 裁剪

flutter engine 本身生成的库 ( ios 对应 Flutter.framework , android 对应 libflutter.so ) 体积比较大,因此我们希望给 engine 本身做一下裁剪,在这一过程当中我们开发了一些工具辅助我们进行这类需求的完成。

linkmap 树状分布

编译工具里面的 ld linker 工具可以通过设置 -Xlinker -Map -Xlinker /path/to/xxx.output.linkmap 参数来生成 linkmap 文件,里面会记录 二进制库 代码段数据段 的分布,我们可以根据这些分布来评估每个模块的占用量,给后续裁剪工作提供一个指向性的目标。

工具分析完 linkmap 之后最终采用 树状图 的方式对模块占用大小进行展示,一目了然,效果如下方所示。

  • Flutter.framework 的构成

ios_linkmap

  • libflutter.so 的构成

android_linkmap

linkmap 文件简介

linkmap 里面会详细记录某个地址区间的信息,[地址, 大小] -> [函数名(变量名),源文件名,二进制库section名,… ],我们只需要按照 linkmap 文件构成去解析获取这些信息,便可以去做一些定制化的聚合统计工作,比如按照 源文件名 当中的目录结构去生成 树状分布图。

  • ios linkmap
1
2
3
4
5
6
7
8
# Object files:
[ 1] obj/flutter/shell/platform/darwin/ios/framework/Source/libFlutter.FlutterAppDelegate.o
# Sections:
# Address Size Segment Section
0x00007820 0x01572DC8 __TEXT __text
# Symbols:
# Address Size File Name
0x00007820 0x000000F4 [ 1] -[FlutterAppDelegate init]
1
2
3
Object files :记录所有的源文件名;
Sections :记录 二进制库 section 的分布情况;
Symbols :记录 函数名/变量名 的地址区间;
  • android linkmap
1
2
3
4
   VMA              LMA     Size Align Out     In      Symbol
1033c0 1033c0 17794e 32 .rodata
1d8c40 1d8c40 9 8 obj/flutter/fml/fml.message_loop_task_queues.o:(.rodata)
1d8c40 1d8c40 8 1 fml::TaskQueueId::kUnmerged

android linkmap 构成比 ios linkmap 简单许多,每一行都记录了 5 个元信息,[地址,地址,大小,位对齐,二进制库section名/源文件名/函数名(变量名)],解析相对简单。

裁剪 boringssl

在树状分布图当中可以看到 boringssl 模块占用了 7 % 左右的大小,属于大小占用较多的 top 模块之一,这个模块在 flutter engine 当中主要给 socket 提供 ssl 的服务,包括证书校验,ssl 握手等等,在 app 当中主要是用于 https 请求的处理,而一般 app 里面都已经有成熟的 http 组件,所以我们可以裁剪掉这个模块,使用 app 的 http 组件代替这部分功能。

1
这个裁剪思路由 头条 率先提出,感谢。
  • DART_IO_SECURE_SOCKET_DISABLED

flutter engine 层通过这个宏可关闭 boringssl 相关功能,接着再移除 boringssl 依赖,修改编译参数即可。

拓展

此外还可以结合 flutter engine 代码覆盖率信息进一步提供裁剪的方向,具体做法会另外开一篇文章介绍。