让你的 XCode 编译链接耗时减半

简介: 让你的 XCode 编译链接耗时减半

如果你在编译链接大项目的时间足够你下楼买杯咖啡了,那请不要按照下面的方法优化它,因为这样的生活确实很惬意。 如果你的公司给你配了 MacBook pro 16 寸顶配版或者是 Mac pro(暖气片、垃圾桶),那也请不要按照下面的方法优化它,因为我酸了...

言归正传,让我们来调教一下我们的好朋友——Xcode。


image.png


Xcode 配置


1.显示编译计时器

您可以直接在 Xcode 的用户界面中启用计时器。默认情况下,此计时器不可见,但是如果您在命令行中运行以下命令,则每次构建应用程序时都会显示时间。

defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES

启用计时器后,您将在 Xcode 的构建状态栏中看到编译应用所需的时间。转到终端并输入:



image.png


2.提高Xcode编译时使用的线程数

不知道哪个版本开始,Xcode 设置中有了 Mac Test Parallelization 和 Simulator Test Parallelization 选项,那我们就用起来吧,大概意思就是 Xcode 在 Test 和 Simulator 干活时用多少线程数。


image.png


当然也可以通过命令行来设置 Xcode 编译时使用的线程数,打开 Mac 终端,然后运行如下命令:

defaults write com.apple.dt.Xcode PBXNumberOfParallelBuildSubtasks 8

Xcode 默认使用与 CPU 核数相同的线程来进行编译,但由于编译过程中的 IO 操作往往比 CPU 运算要多,因此适当的提升线程数可以在一定程度上加快编译速度。如果你的 Mac 采用的是 4 核的 CPU,那将线程数改为 8 后编译速度略有提升。


3.将 Build Active Architecture Only 改为 Yes

在工程对应 Target 的 Build Settings 中,找到 Build Active Architecture Only 这一项,将 Debug 时的 No 改为 Yes。

这一项设置的是,是否仅编译当前架构的版本,如果为 No,会编译所有架构的版本。需要注意的是,此选项在Release 模式下必须为 Yes,否则发布的 ipa 在部分设备上将不能运行。这一项更改完之后,可以显著提高编译速度。


image.png


当 Debug 和 Release 属性设置为 YES 时,是为了 debug 的时候编译速度更快,它只编译当前的 architecture 版本,当而设置为NO时,会编译所有的版本,编译出的版本是向下兼容的,比如你设置值为 YES,用 iPhone4 编译出来的是 armv7 版本的,iphone5 也可以运行,但是 armv6 的设备就不能运行。

目前为止Apple移动设备默认指令集:

  • armv6:iPhone2G/3G、iPod 1G/2G
  • armv7:iPhone 3GS/4/4s、iPod 3G/4G、iPad 1G/2G/3G、iPad mini
  • armv7s:iPhone5、iPhone5c、iPad4
  • arm64:iPhone5s及以后、iPad Air、iPad mini2

(armv6、armv7、armv7s、arm64 都是 arm 处理器的指令集,所有指令集原则上都是向下兼容的。需要注意的是 iOS 模拟器没有运行 arm 指令集,编译运行的是 x86 指令集,所以,只有在 iOS 设备上,才会执行设备对应的 arm 指令集。)


4.使用新的构建系统

Apple 在 Xcode 9 中启动了新的构建系统,但默认情况下未激活它。苹果的 “New Build System” 完全用 Swift 编写,旨在提高整体性能和依赖性管理。但是,对于 Xcode 10,默认情况下会激活新的构建设置,并从 Xcode Files-> Project/Workspace Settings 可以打开设置。


image.png


你也可以用命令行设置使用,方法如下:

xcodebuild -UseNewBuildSystem=YES


5.识别导致更长编译时间的函数和表达式

Xcode 具有内置功能,可让您识别导致更长编译时间的函数和表达式。您可以指定编译时间限制,并在代码库中标识超出此限制的区域。

在项目构建设置 “Other Swift Flags” 中添加以下行:


image.png


300 表示您在函数和表达式上放置的编译时间限制,以毫秒为单位。

-Xfrontend -warn-long-function-body = 300 
-Xfrontend -warn-long-expression-type-checking = 300

如果函数或表达式花费的时间超过指定的时间,则此标志将警告您。这意味着您必须优化函数或表达式。


image.png


6.增加为 Swift 项目运行的并发构建任务的数量

在 Xcode 9.2 中,Apple 引入了一项实验性功能,该功能允许 Xcode 并行运行 Swift 构建任务。默认情况下,此功能未启用,您需要从命令行将其打开。

defaults write com.apple.dt.Xcode BuildSystemScheduleInherentlyParallelCommandsExclusively -bool YES


7.删除“Run Script Phase”

删除“Run Script Phase”,像 SwiftLint,Twine 等,当然如果你需要他们那就保留吧。


8.并行构建

此选项允许 Xcode 通过构建不同时依赖于彼此的目标来加快总构建时间。这在具有许多较小依赖项的项目上可以节省时间,这些依赖项可以轻松并行运行。

在 Xcode 10 中打开项目时,应该已经启用了构建并行化。要检查或更改此选项,请打开方案编辑器,在边栏中选择“Build”,并确保在顶部选中了“Parallelize Build”。


image.png


适当的构建设置


1.将 Debug Information Format 改为 DWARF

在工程对应 Target 的 Build Settings 中,找到 Debug Information Format 这一项,将 Debug 时的 DWARF with dSYM file 改为 DWARF。

这一项设置的是,是否将调试信息加入到可执行文件中,改为 DWARF 后,如果程序崩溃,将无法输出崩溃位置对应的函数堆栈,但由于 Debug 模式下可以在 Xcode 中查看调试信息,所以改为 DWARF 影响并不大。这一项更改完之后,可以大幅提升编译速度。


image.png


2.整个模块优化(WMO)

在 Xcode 中,我们可以选择三个优化级别:无,快速和快速,整个模块优化。 使用整体模块优化使编译非常快。但是,选择快速还是快速,整个模块优化将不允许开发人员调试应用程序。


image.png


代码优化


1.技巧和窍门

a.下载 Xcode 的构建时间分析器,它可以直观地告诉您代码的每个部分编译所花费的时间。 github.com/RobertGumme…


image.png


b.通过上面第五点,找到耗时代码,精准优化代码。 c.在类本身的扩展的方法中对方法进行基准测试。 d.添加类型注释,以便编译器不需要推断类型。 e.避免三元运算符 ? :。 f.避免通过手动展开东西来避免零合并运算符 if let。 g.使用字符串插值而不是串联。


2.第三方依赖

有两种非常流行的依赖项管理技术/工具:Cocoa Pod,Carthage,Swift 软件包管理器,git 子模块。

在 iOS 项目中处理第三方依赖关系的最常见方法是使用 CocoaPods。它很容易使用,但如果您关心构建时间,则不是最佳选择。

可以使用的一种替代方法是 Carthage。它比 CocoaPods 稍稍繁琐,但可以缩短构建时间。


3.优化CocoaPods

如果您使用 CocoaPods,则可以通过在 Podfile 的末尾添加以下内容来优化所有依赖项。

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      if config.name == 'Debug'
        config.build_settings['OTHER_SWIFT_FLAGS'] = ['$(inherited)', '-Onone']
        config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] = '-Owholemodule'
      end
    end
  end
end


4.对代码进行少量更改

a.当您知道不需要覆盖声明时,请使用 “final”。该 final 关键字是一个类的声明,一个方法或属性,使得声明不能被覆盖的限制。这意味着编译器可以发出直接函数调用,而不是间接调用。 b.当不需要在文件外部访问声明时,请使用 “private” 和 “fileprivate”。将 privateor 或 fileprivate 关键字应用于声明会限制该声明在声明它的文件中的可见性。这使编译器能够确定所有其他可能覆盖的声明。 c.在数组中使用值类型:在 Swift 中,类型可以分为两个不同的类别:值类型(结构,枚举,元组)和引用类型(类)。一个关键的区别是,值类型不能包含在 NSArray 中。因此,当使用值类型时,优化器可以消除 Array 中大部分的开销,这些开销对于处理数组支持 NSArray 的可能性是必需的。 d.当不需要 NSArray 桥接时,可以将 ContiguousArray 与引用类型一起使用。如果您需要引用类型的数组,并且该数组不需要桥接到 NSArray,请使用 ContiguousArray 而不是 Array:

class C { ... }
var a: ContiguousArray<C> = [C(...), C(...), ..., C(...)]


参考



目录
相关文章
|
图形学 Android开发 iOS开发
|
9月前
|
JSON 缓存 监控
Xcode项目编译优化
随着项目工程的迭代,代码量不断的增加,扩展功能不断的被引入,项目的整体编译时间开始变长。
263 0
Xcode项目编译优化
|
9月前
|
搜索推荐 iOS开发 芯片
记录一次Xcode 模拟器项目编译问题
记录一次Xcode 模拟器项目编译问题
记录一次Xcode 模拟器项目编译问题
|
存储 缓存 开发工具
Xcode 清理大法
Xcode 清理大法
854 0
|
编解码
doubango的帧率太低,怎么解决?
doubango的帧率太低,怎么解决?
65 0
|
iOS开发
iOS 统计Xcode项目代码行数
iOS 统计Xcode项目代码行数
217 0
|
iOS开发
iOS Xcode文件夹内文件乱序解决办法
iOS Xcode文件夹内文件乱序解决办法
797 0
|
图形学
Unity 减小包体apk大小技巧
创建一个新的工程,默认场景打包的包体如下 更改Other Settings中的Device Filter,但是弊端就是牺牲了机器的兼容性 更改Device Filter选项为ARMv7后的包体如下: ...
1922 0