VC2017编译的尺寸优化

发布者:blowfish
发布于:2017-12-07 17:42
优化是一种场景相关的权衡,看是速度优先,还是尺寸优先,或者是二者的折衷。在一个手机app动则几十上百兆而且隔三差五就要耗流量进行升级的今天,PC机上却还是有需要做exe/dll尺寸优化的场景。最近折腾了一下OpenSSL编译的裁剪,顺带把VC2017的尺寸优化做一下简单笔记。

1、首先是/O1(Minimize Size)选项,这个可能会降低程序的运行效率,通常不用,而是用默认的/O2(Maximize Speed)。


2、/arch:IA32(No Enhanced Instructions)。这个是采用古老的386指令集而不生成MMX、AVX等“新”指令,通常生成的代码尺寸较小(只是经验值)。新的指令集,理论上效率要高一些。具体怎么选择就是看所要支持的CPU型号。OpenSSL的编译脚本“perl Configure VC-WIN32  386"可以指定只使用386指令集,如果不带386参数,会根据cpuid的检测结果动态决定采用什么指令集,也就是会存在多套指令集共存完成同样的功能,编译出来的尺寸会大一点。当然,OpenSSL的这个386配置参数,控制它的perl脚本在预生成优化用的汇编代码时采用什么指令集,但目前并没给cl.exe增加/arch:IA32参数,所以编译32位的OpenSSL时需要手动修改ms\nt.mak加上这个参数,以便编译*.c时只生成386指令集。


3、/Gy(Enable Function-Level Linking)选项。这个是默认的设置,基本上也是必开的项。 这个选项告诉编译器将一些函数(具体是哪些函数,编译器自行决定)打包放到单独的section中,这有个专有名词叫COMDAT,即common data,意思是打包的函数或者打包的数据。按微软大拿Raymond Chen的说法,COMDAT这个概念最早来自FORTRAN语言。gcc和llvm对COMDAT都有对应的支持。链接器在链接阶段,可以对COMDAT中重复的函数进行消重(folding,折叠)。如果编译器不把函数打包成COMDAT项,链接器是不敢贸然优化掉对应的函数的,因为缺少这些函数的引用信息。


4、/GL(Whole Program Optimization)选项。基本上也是必开的项。告诉编译器做跨模块的优化。


5、/LTCG(Link-time Code Generation)选项。基本上也是必开的项。进行全局/跨模块的优化。这个选项有一些子选项是根据试运行的情况来做优化的(Profile Guided Optimization),类似于“开着Xperf跑用例,然后分析Xperf记录的数据,以决定优化哪里以及怎么优化”,只不过是编译器帮着干它所能干的。/LTCG选项开了之后,才能开/GL。


6、/Gw(Optimize Global Data)选项。基本上也是必开的项。/Gy是把函数打包成COMDAT项,而/Gw是把数据打包成COMDAT项,一般是全局只读的数据,并且这些数据没有被代码做取地址操作。/Gw是从VC2013开始引入的,微软最初可能是出于优化自己的产品尺寸的需要,不过也算是体恤码农了。


7、/OPT:REF(Optimize References)选项。基本上也是必开的项。这个选项把COMDAT中没被引用的函数、数据都给优化掉,编译产物的尺寸当然大大减小。前提是已经开了/Gy、/Gw把函数、数据都打包成COMDAT项了。


8、/OPT:ICF(Identical COMDAT Folding)选项。基本上也是必开的项。这个选项把COMDAT中重复的函数、数据都给优化掉,只保留一份,效果也是产物的尺寸减小。前提也是已经开了/Gy、/Gw。开/OPT:REF时,编译器会自动开一部分/OPT:ICF的功能。另外,由于/OPT:ICF对函数、数据消重了,而如果你的代码正好是假定这些被消重的函数、数据的地址不同,那就会出问题,也就是说/OPT:ICF在特定情况下存在一定的副作用,不过我们的代码通常不会正好躺枪。


9、__declspec(selectany)编译指示。告诉编译器将对应的全局变量、全局对象、静态成员变量等数据打包成COMDAT项。一般不推荐在*.h/*.hpp头文件中定义变量,万一要定义的话,最好用 __declspec(selectany)修饰一下,方便进行尺寸优化。这个编译指示相当于一个更细粒度的/Gw选项。


参考:


Introducing ‘/Gw’ Compiler Switch

https://blogs.msdn.microsoft.com/vcblog/2013/09/11/introducing-gw-compiler-switch/


Why is Identical COMDAT Folding called Identical COMDAT Folding?

https://blogs.msdn.microsoft.com/oldnewthing/20161024-00/?p=94575


声明:该文观点仅代表作者本人,转载请注明来自看雪