第八项【so】不规范使用STL,是指动态链接库so对c STL库的不规范使用,包括两种情况:动态链接非统一STL,官方建议统一使用的STL为libc _shared.so,其它非统一STL包括libgnustl_shared.so、libstlport_shared.so;静态链接stl,通过改造为动态链接,可以实现较好的瘦身收益。分析报告中的示例结果如下:
第九项【so】无用导出符号。动态链接库的导出符号(exported symbol),是指在so内定义的对象、方法、全局变量,被设置为可被外部代码引用(导入)。无用导出符号,则是指在依赖这个so的其它so中(apk范围内),未找到任何引用,当然这里存在以下情况需要特殊处理:JNI方法、通过dlsym方式加载并调用的符号。对于确实无用的导出符号,可以在编译so时设置为不导出。具体操作方式并不唯一,比较建议使用编译选项-fvisibility=hidden,同时显示对需要导出符号增加 attribute ((visibility ("default")))标记这套方案来实现,这样新增符号默认不会导出,不至于出现一段时间没人管,无用导出符号持续累积问题。分析报告中的示例结果如下:
3.3 卡口能力建设
后者在研发迭代过程中,低成本维持常态化治理模式的关键之一,其承载的三个核心价值如下:
去中心,需要能够对apk大小进行适当颗粒度的精准拆分,用于卡口阈值、检测以及不通过时进行拦截。
促前置。包大小和代码规范、bug等单点问题不同,无法通过就地修改来完成瘦身,往往需要通过“拆东墙补西墙”的方式,寻找存量可瘦身空间来弥补新功能带来的增量。所以,只有足够前置才能留出更多时间给瘦身治理,从而保障最终发布到用户手中的apk大小保持稳定。前置要求卡口必须在代码变更后“第一时间”发挥作用,识别到包大小变化,如果超过阈值则进行拦截。这个“第一时间”根据不同app迭代模式差异,选取适当的节点即可,例如优酷的一个版本迭代可以分为“提测-集成-灰度-发布”四个流程节点,那么就选择提测和集成两个节点部署卡口。
低成本。卡口是一个比较模糊的概念,1百个工程师可能会有1百个对卡口具体机制的理解和设计,对于包大小卡口本身一定要具备的是低成本维护,包括以下几个方面:
- 与研发流程结合。包大小卡口不是一套独立的流程,而是要融入到整个研发流程中,尽可能减少额外使用成本。
- 100%覆盖。一定是要对所有可能的增量来源,都能够覆盖到,不能存在某种方式,可以绕过卡口机制。一旦被绕过,会拉高后续的识别&治理成本。
- 100%自动化。这一点看起来有点像废话,卡口难道还能手动执行?现实情况是,有些场景下所谓的“卡口”,其实自动化程度较低,还需要不小的人工参与。
优酷在2018年就建立了包大小卡口能力,后续的演进和调整都是朝着更贴合上述核心价值的方向进行,直至2021年初才达到稳定有效的成熟状态。包大小卡口由分析工具franky、卡口能力平台、研发流程管控平台(CI/CD平台)三部分组成,示意图如下: