Swift4.1新增代码size优化模式



  • 本篇为译文,原文可见:https://swift.org/blog/osize/


    Swift 4.1 编译器开始支持一种新的优化模式,该模式将通过专门优化来减少代码大小。

    Swift编译器带来了强大的优化。当通过 -O 参数进行编译,编译器将尝试转化代码以便于能以最佳性能执行。然而运行时性能的提升有时候也要考虑增加的代码大小。伴随着新的优化模式 -Osize的到来,用户可以选择以最小代码大小进行编译,而不是最佳性能。

    可以使用 -Osize 代替 -O 来开启 size 优化模式。Xcode 9.3 中设置如下:

    https://swift.org/assets/images/osize-blog/Xcode-Osize-setting.png

    同时,该模式可以独立应用于单个文件或整个模块。

    https://swift.org/assets/images/osize-blog/Xcode-mode-setting.png

    -Osize 模式虽然既可以应用于单个文件,也可以应用于整个模块,但是后者可以带来最佳的优化效果。

    对于某些项目,-Osize模式减少了 5% - 30% 的代码大小。

    但是性能又如何呢?这完全取决于项目。对于大多数应用来说,-Osize模式将会影响到运行性能,比如可能会降低 5% 。但是对于性能要求比较高的项目来说,-O可能仍然是更好的选择。

    代码优化的影响

    我们来比较下两种模式的不同。-Osize模式与-O模式类似,但不同之处是,-Osize模式下,编译器会尝试避免重复的代码。举例来说,编译器根据 size 大小限制来决定一个函数是否需要被内联。

    如果因为内联函数增加了代码大小而选择完全禁止它的话,将不是一个好办法。比如,考虑以下简单的 getter 方法:

    struct X {
      var x: Int { return 27 }
    }
    

    如果频繁调用该 getter 方法,内联方式将会更合适。当然这是一个极端的例子,但是也证明了某些时候内联仍然是一种有效方式。另外,内联函数可以触发其它方面的优化,进而减少代码大小。举个例子,如下的代码片段如果通过内联方式的话,将会事先计算得出a.x的值,进而整个 if分支都将得到优化。

    func foo(a: X) {
    	if a.x != 27 {
    		// Can be optimized away if the getter of a.x is inlined
    	}
    }
    

    通过-Osize编译器也会有其它方面的优化。比如,一些用来处理 generic types 或者 Objective-C 桥接的代码将会被提取到 helper functions,而不是使用内联方式。

    结论

    如果对于性能不是很敏感的话,-Osize优化模式将会有效减少程序代码大小。


Log in to reply