@H_502_1@
@H_502_1@上周我拜读了Nickoneill的佳作《加速Swift的构建》,之后便不由稍微换了个角度来看待Swift的代码。 @H_502_1@
@H_502_1@目前有一个新问题出现:是否该将一行可以算是简洁的代码重构为9行代码,以便符合编译器的需求?对于代码来说,简洁与编译器友好孰轻孰重?其实,这取决于项目的规模以及开发者的意愿。 @H_502_1@
@H_502_1@等等,有一个Xcode插件 @H_502_1@
@H_502_1@在举例之前,我先强调一下手动过滤日志文件是非常耗时的。有人设计出了终端命令来简化这一步骤,不过我的方法更进一步,使用了Xcode插件。 @H_502_1@
@H_502_1@虽然初衷只是为了找到并修复最耗时的部分,不过目前我的看法也已经发生了变化:将该过程当成迭代的过程。这样的做法不仅可以让代码构建效率更高,也能在最开始就防止项目中出现过于耗费时间的函数。 @H_502_1@
@H_502_1@不少的惊喜
@H_502_1@
@H_502_1@我时常来来回回地查看不同的Git branch,等待一个项目花费很长时间编译结束,一直没想出来为什么一个小项目(大约2万行Swift代码)要花那么久时间构建。 @H_502_1@
@H_502_1@在了解到真正的原因后,我必须承认:一行代码也需要好几秒来编译这件事吓了我一跳。 @H_502_1@
@H_502_1@我们来看几个例子! @H_502_1@
@H_502_1@空合运算符(Nil Coalescing Operator) @H_502_1@
@H_502_1@很显然,编译器肯定不喜欢第一种编译方法,在拆成两个视图之后,构建时间减少了99.4%。 @H_502_1@
@H_502_1@ArrayOfStuff + [Stuff] @H_502_1@
@H_502_1@在代码中经常是像下面这样: @H_502_1@
@H_502_1@我经常会这样写代码,而这种方式对代码的构建时间有很大影响。下面是差距最大的一个案例,构建时间减少了97.9%。 @H_502_1@
@H_502_1@三元运算符(Ternary operator) @H_502_1@
@H_502_1@使用if else语句代替了三元运算符,而不进行其它任何改动,构建时间就能缩短92.9%。如果用for循环来代替map,构建时间又会缩短75%(不过for循环太伤眼了)。 @H_502_1@
@H_502_1@在CGFloat中去掉CGFloat @H_502_1@
@H_502_1@这句话有点费解,其实在CGFloat中,有些括号是多余的,清除掉之后,构建时间会缩短99.9%。 @H_502_1@
@H_502_1@Round() @H_502_1@
@H_502_1@这个真的很奇怪,下面样例中的变量混合了本地与实例变量,问题很可能不在rounding本身,而是由于在方法中混用代码而导致的,去掉它之后就能大幅缩减所用的时间,准确来讲耗费时长减少了97.6%。 @H_502_1@
@H_502_1@注意:所有的对比测量都是在MacBook Air(13英寸,Mid 2013款)上进行的。 @H_502_1@
@H_502_1@试一下吧
@H_502_1@
@H_502_1@无论你是否遇到了构建速度缓慢的问题,了解到底是什么会让编译器遇到混乱情况都是很有用的。我肯定你也能发现不少惊喜,作为参考,下面是在我的项目中需要花费5秒多时间构建的完整代码。 @H_502_1@
@H_502_1@
@H_502_1@
@H_502_1@第一时间掌握最新移动开发相关信息和技术,请关注mobilehub公众微信号(ID: mobilehub)。 @H_502_1@
@H_502_1@原文: Regarding Swift build time optimizations @H_502_1@作者: Robert Gummesson @H_502_1@译者: 孙薇 @H_502_1@审校: 唐小引(@唐门教主),欢迎技术投稿、约稿,给文章纠错,请发送邮件[email protected]@H_502_1@
@H_502_1@上周我拜读了Nickoneill的佳作《加速Swift的构建》,之后便不由稍微换了个角度来看待Swift的代码。 @H_502_1@
@H_502_1@目前有一个新问题出现:是否该将一行可以算是简洁的代码重构为9行代码,以便符合编译器的需求?对于代码来说,简洁与编译器友好孰轻孰重?其实,这取决于项目的规模以及开发者的意愿。 @H_502_1@
@H_502_1@等等,有一个Xcode插件 @H_502_1@
@H_502_1@在举例之前,我先强调一下手动过滤日志文件是非常耗时的。有人设计出了终端命令来简化这一步骤,不过我的方法更进一步,使用了Xcode插件。 @H_502_1@
@H_502_1@虽然初衷只是为了找到并修复最耗时的部分,不过目前我的看法也已经发生了变化:将该过程当成迭代的过程。这样的做法不仅可以让代码构建效率更高,也能在最开始就防止项目中出现过于耗费时间的函数。 @H_502_1@
@H_502_1@不少的惊喜
@H_502_1@
@H_502_1@我时常来来回回地查看不同的Git branch,等待一个项目花费很长时间编译结束,一直没想出来为什么一个小项目(大约2万行Swift代码)要花那么久时间构建。 @H_502_1@
@H_502_1@在了解到真正的原因后,我必须承认:一行代码也需要好几秒来编译这件事吓了我一跳。 @H_502_1@
@H_502_1@我们来看几个例子! @H_502_1@
@H_502_1@空合运算符(Nil Coalescing Operator) @H_502_1@
@H_502_1@很显然,编译器肯定不喜欢第一种编译方法,在拆成两个视图之后,构建时间减少了99.4%。 @H_502_1@
@H_502_1@// Build time: 5238.3ms @H_502_1@return CGSize(width: size.width + (rightView?.bounds.width ?? 0) + (leftView?.bounds.width ?? 0) + 22,height: bounds.height) @H_502_1@@H_502_1@
@H_502_1@// Build time: 32.4ms @H_502_1@var padding: CGFloat = 22 @H_502_1@if let rightView = rightView { @H_502_1@ padding += rightView.bounds.width @H_502_1@} @H_502_1@
@H_502_1@if let leftView = leftView { @H_502_1@ padding += leftView.bounds.width @H_502_1@} @H_502_1@return CGSizeMake(size.width + padding,bounds.height)
@H_502_1@ArrayOfStuff + [Stuff] @H_502_1@
@H_502_1@在代码中经常是像下面这样: @H_502_1@
@H_502_1@return ArrayOfStuff + [Stuff] @H_502_1@// rather than @H_502_1@ArrayOfStuff.append(stuff) @H_502_1@return ArrayOfStuff@H_502_1@
@H_502_1@我经常会这样写代码,而这种方式对代码的构建时间有很大影响。下面是差距最大的一个案例,构建时间减少了97.9%。 @H_502_1@
@H_502_1@// Build time: 1250.3ms @H_502_1@let systemOptions = [ 7,14,30,-1 ] @H_502_1@let systemNames = (0...2).map{ String(format: localizedFormat,systemOptions[$0]) } + [NSLocalizedString("everything",comment: "")] @H_502_1@// Some code in-between @H_502_1@labelNames = Array(systemNames[0..<count]) + [systemNames.last!] @H_502_1@@H_502_1@
@H_502_1@// Build time: 25.5ms @H_502_1@let systemOptions = [ 7,-1 ] @H_502_1@var systemNames = systemOptions.dropLast().map{ String(format: localizedFormat,$0) } @H_502_1@systemNames.append(NSLocalizedString("everything",comment: "")) @H_502_1@// Some code in-between @H_502_1@labelNames = Array(systemNames[0..<count]) @H_502_1@labelNames.append(systemNames.last!)
@H_502_1@三元运算符(Ternary operator) @H_502_1@
@H_502_1@使用if else语句代替了三元运算符,而不进行其它任何改动,构建时间就能缩短92.9%。如果用for循环来代替map,构建时间又会缩短75%(不过for循环太伤眼了)。 @H_502_1@
@H_502_1@// Build time: 239.0ms @H_502_1@let labelNames = type == 0 ? (1...5).map{type0ToString($0)} : (0...2).map{type1ToString($0)} @H_502_1@@H_502_1@
@H_502_1@// Build time: 16.9ms @H_502_1@var labelNames: [String] @H_502_1@if type == 0 { @H_502_1@ labelNames = (1...5).map{type0ToString($0)} @H_502_1@} else { @H_502_1@ labelNames = (0...2).map{type1ToString($0)} @H_502_1@}
@H_502_1@在CGFloat中去掉CGFloat @H_502_1@
@H_502_1@这句话有点费解,其实在CGFloat中,有些括号是多余的,清除掉之后,构建时间会缩短99.9%。 @H_502_1@
@H_502_1@// Build time: 3431.7 ms @H_502_1@return CGFloat(M_PI) * (CGFloat((hour + hourDelta + CGFloat(minute + minuteDelta) / 60) * 5) - 15) * unit / 180 @H_502_1@@H_502_1@
@H_502_1@// Build time: 3.0ms @H_502_1@return CGFloat(M_PI) * ((hour + hourDelta + (minute + minuteDelta) / 60) * 5 - 15) * unit / 180
@H_502_1@Round() @H_502_1@
@H_502_1@这个真的很奇怪,下面样例中的变量混合了本地与实例变量,问题很可能不在rounding本身,而是由于在方法中混用代码而导致的,去掉它之后就能大幅缩减所用的时间,准确来讲耗费时长减少了97.6%。 @H_502_1@
@H_502_1@// Build time: 1433.7ms @H_502_1@let expansion = a — b — c + round(d * 0.66) + e @H_502_1@// Build time: 34.7ms @H_502_1@let expansion = a — b — c + d * 0.66 + e@H_502_1@
@H_502_1@注意:所有的对比测量都是在MacBook Air(13英寸,Mid 2013款)上进行的。 @H_502_1@
@H_502_1@试一下吧
@H_502_1@
@H_502_1@无论你是否遇到了构建速度缓慢的问题,了解到底是什么会让编译器遇到混乱情况都是很有用的。我肯定你也能发现不少惊喜,作为参考,下面是在我的项目中需要花费5秒多时间构建的完整代码。 @H_502_1@
@H_502_1@import UIKit @H_502_1@@H_502_1@
@H_502_1@class cmexpandingTextField: UITextField { @H_502_1@
@H_502_1@ func textFieldEditingChanged() { @H_502_1@ invalidateIntrinsicContentSize() @H_502_1@ } @H_502_1@
@H_502_1@ override func intrinsicContentSize() -> CGSize { @H_502_1@ if isFirstResponder(),let text = text { @H_502_1@ let size = text.sizeWithAttributes(typingAttributes) @H_502_1@ return CGSize(width: size.width + (rightView?.bounds.width ?? 0) + (leftView?.bounds.width ?? 0) + 22,height: bounds.height) @H_502_1@ } @H_502_1@ return super.intrinsicContentSize() @H_502_1@ } @H_502_1@}
@H_502_1@
@H_502_1@
@H_502_1@第一时间掌握最新移动开发相关信息和技术,请关注mobilehub公众微信号(ID: mobilehub)。 @H_502_1@
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。