3.3.1 包体优化:二进制代码文件

对二进制代码文件大小的优化能够有效地减小包体体积,下面将介绍几种方法来减小二进制代码文件的大小。

3.3.1.1 不导出非必要的符号表

通过精简符号表,可以减小应用程序的体积,提高应用程序的性能。UE集成的第三方库的符号表都可以不导出。在iOS中,动态库导出符号表是通过指定 Export-Symbols-List 来过滤的。在Android中,通过Version Script把不需要的符号表去掉。这样处理后,UE代码大小能减少大概9MB左右。

3.3.1.2 Relocation Section压缩

Relocation Section是可执行文件或共享库中的一部分,它包含了程序运行时需要进行重定位的位置信息。Global Data是指在程序中定义的全局变量或全局数据,它们的地址在程序运行时是固定的。当程序需要被加载到不同的地址空间时,Global Data需要被Relocation Section中的重定位项修正,以确保程序能够正常访问这些全局数据。如果程序中的Global Data过多,会导致Relocation Section中的重定位项数增加,进而导致可执行文件或共享库的大小增加。这不仅会占用更多的磁盘空间,还可能降低程序的性能,因为加载Relocation Section中的重定位项需要额外的时间和内存开销。

UE中有大量的Global Data,那么这些Global Data在被编译成符号表,并变成动态库之后,所有的内容都需要做重定向。最初在讨论如何减小二进制代码文件大小的测试过程中发现,Android的ELF格式和iOS的Mach-O格式最终表现的大小差别很大。Android后续的一些版本,支持了一些特定的重定向表的格式,像REL/RELA、RELR、APS2等[5]。由于最低需要支持Android 6.0版本,所以选择了REL/RELA这种格式进行处理。通过这种方式,能节省大概18MB左右的存储空间。

所以在代码中应尽可能减少这些Global Data及静态对象等内容的使用。比如,可以延迟地把常量数据分配在Heap段,这样也能保证二进制代码文件不会增大。

3.3.1.3 精简不必要的功能

根据项目需求针对一些模块做精简,如并不需要Chaos、ICU的这些库,可以将它们替代掉。

3.3.1.4 修改编译选项

修改编译选项也可以缩减二进制代码文件的大小,如表3.2所示。使用Oz后性能会有些下降,性能损耗大概在5%左右,是一个可接受的范围。

表3.2 编译选项优化后的数据

3.3.1.5 数据结果

表3.3展示了iOS平台和Android平台优化后的最终代码文件大小的对比,可以看到,二进制代码文件的大小相较早期的版本有了大幅降低。

表3.3 二进制文件优化前后的数据