结论先行
-
使用Xcode 14重新构建我们的App产物,可以优化2%的OC代码大小(基于message send stub)。
-
将deployment target设置为iOS 16开始,可以再优化2%的代码大小。
感想:
-
换机潮 可能就在不知不觉间帮助完成了一些技术优化目标。
-
发现问题-定义问题-解决问题,从全链路/场景生命周期来看:
App生命周期 : [Coding] -> [Compiling] -> [Linking] -> [Running]
第一个2%
Apple针对OC代码中随处可见的_objc_msgSend指令的字节大小做了优化。
扩展阅读:mikeash.com: Friday Q&A 2009-03-20: Objective-C Messaging
目前,一次msgSend调用是12字节,在ARM64上 每一条占据4个字节空间:
由于每次调用都是相同的指令,所以可以通过提供stub方法来做代码复用,接收传参:
抽出可复用的代码来调用,能节省指令占用的字节空间。
但是多出了调用次数,也就相当于多出了JUMP指令,会影响性能。
所以,Apple默认的是 Size-Performance-Balanced的方案,开发者可以自己指定编译选项来追求更多的代码大小优化空间。
第二个2%
另一个类似的是ARC机制下,编译器为我们隐式插入的、同样随处(不)可见的retain/release指令:
由于retain/release实际上插入的是C方法,
所以,为了遵循平台ABI的调用约定,编译指令上需要多做一点事,将要操作的目标对象指针传递到指定寄存器上(mov指令)。
比如下述汇编的作用是将通用寄存器x20的值,按照方法调用约定 复制到x0寄存器上(方法调用参数按照约定通常放到x0~x7 这几个寄存器上)。
Apple通过为retain/release指定了新的自定义调用约定,将字节大小从8bytes优化到4bytes,并在所有代码里放大这个效果。
这个优化点看起来有点酷,但我还没太明白具体是怎么work的,比如哪个节点来负责解析这条指令,原来的ABI调用约定是操作x0寄存器,现在直接可以在x19/x20上玩?
因为这里的优化效果,需要在iOS 16的runtime上,所以怎么结合的,我还没搞清楚,求指点。
最后,是一个对autoreleasepool的优化(使用更轻量的return address来取代特殊指令做判断),不过只给了定性的优化,没有定量。