前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Xcode编译疾如风系列-1.分析编译耗时

Xcode编译疾如风系列-1.分析编译耗时

作者头像
ChildhoodAndy
发布2021-04-23 14:50:32
4.6K0
发布2021-04-23 14:50:32
举报
文章被收录于专栏:小菜与老鸟小菜与老鸟

Xcode 编译疾如风-1.如何排查编译耗时问题

开发 iOS 的小伙伴都知道,随着项目的不断庞大,Xcode 项目的编译时间也会越来越长。如果不加管控,会严重影响到我们的开发效率。

全量编译下,我去,30 分钟过去了,拉个屎还能抽根烟...

这不,小菜有些受不了了。开始研究 iOS 编译时长问题。

切入这个编译耗时问题,首先我们要分析编译的耗时在哪里,然后再针对性的进行优化。否则就像无头苍蝇一样乱飞乱撞,事倍功半。

关于这个系列文章有几点说明:1)这个系列会涉及到 Cocoapods,小菜的项目使用该工具进行组件管理。2)标题中提到的编译会涉及到全量编译和增量编译。

我们如何衡量构建时间呢?或者我们有哪些工具能够帮助我们分析构建时间?

ShowBuildOperationDuration

我们暂时先不看pod install或者pod update的组件安装耗时,单纯看 Xcode 的 build 耗时情况。如何得知 Xcode build 项目的时长?

一句命令行搞定:

代码语言:javascript
复制
defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES

终端执行完毕后,我们在使用 Xcode 编译时,便会在 Xcode 的状态条上显示编译时长

有读者朋友问了,如果我不用 Xcode 软件编译呢,比如我使用xcodebuild来编译,怎么获取到编译耗时呢?

代码语言:javascript
复制
time xcodebuild

很简单,shell 的基本操作,使用time便可获取执行的时间情况。

Build With Timing Summary

构建时长概要

同样的,如果我们用xcodebuild也可以获取构建时长概要:

代码语言:javascript
复制
xcodebuild -showBuildTimingSummary

XCLogParser

XCLogParser[1] 是一个命令行工具,用于分析 xcactivitylog 日志文件(注:xcactivitylog 是 Xcode 和 xcodebuild 在构建时保存的一种日志文件)

XCLogParser 可以提供项目中每个模块和文件的构建时间警告错误单元测试结果

我们在项目编译后,执行脚本:

代码语言:javascript
复制
xclogparser parse --project Kickstarter --reporter html

便可以在build/xclogparser/reports/时间戳目录下看到输出了大量的html,直接点击里面的index.html便可在浏览器中查看具体的编译信息。

我们可以将脚本执行在自动构建 CI 流程中,打完包后可以查看 CI 机器下生成的编译信息。CI 机器起一个静态服务即可。

Swift 代码编译耗时分析

如果项目中存在大量的 Swift 代码,且 Swift 的编译耗时成为了瓶颈,我们可以对 Swift 代码的编译耗时情况进行诊断。

类型检查警告

我们可以在Other Swift Flags配置检查警告项:

代码语言:javascript
复制
-Xfrontend -warn-long-function-bodies=100
-Xfrontend -warn-long-expression-type-checking=100

然后 Xcode 编译结束后,我们便可以在编译日志中看到函数/表达时编译耗时超过 100毫秒 的警告,点击这些警告便可以进入具体的代码位置,从而帮助我们优化代码。

编译器诊断选项

Swift 编译器性能[2]中,Apple 官方提到了几个诊断选项:

  • -driver-time-compilation
  • -Xfrontend -debug-time-function-bodies
  • -Xfrontend -debug-time-expression-type-checking
  • -Xfrontend -print-stats
  • -Xfrontend -print-clang-stats
  • -Xfrontend -print-stats -Xfrontend -print-inst-counts

我们重点关注-debug-time-function-bodies-debug-time-expression-type-checking

-debug-time-function-bodies可以统计打印出 Swift 文件中函数体编译耗时:

代码语言:javascript
复制
9.16ms  test.swift:15:6 func find<R>(_ range: R, value: R.Element) -> R where R : IteratorProtocol, R.Element : Eq
0.28ms  test.swift:27:6 func findIf<R>(_ range: R, predicate: (R.Element) -> Bool) -> R where R : IteratorProtocol
2.81ms  test.swift:40:6 func count<R>(_ range: R, value: R.Element) -> Int where R : IteratorProtocol, R.Element : Eq
0.64ms  test.swift:51:6 func countIf<R>(_ range: R, predicate: (R.Element) -> Bool) -> Int where R : IteratorProtocol
...

例如

代码语言:javascript
复制
xcodebuild -project 'Kickstarter.xcodeproj' \
-scheme 'Kickstarter-iOS' \
-configuration 'Debug' \
-sdk 'iphonesimulator' \
clean build \
OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-compilation" |
    awk '/CompileSwift normal/,/Swift compilation/{print; getline; print; getline; print}' |
    grep -Eo "^CompileSwift.+\.swift|\d+\.\d+ seconds" |
    sed -e 'N;s/\(.*\)\n\(.*\)/\2 \1/' |
    sed -e "s|CompileSwift normal x86_64 $(pwd)/||" |
    sort -rn |
    head -3

25.6026 seconds Library/ViewModels/SettingsNewslettersCellViewModel.swift
24.4429 seconds Library/ViewModels/PledgeSummaryViewModel.swift
24.4312 seconds Library/ViewModels/PaymentMethodsViewModel.swift

-debug-time-expression-type-checking更细致,可以打印出表达式的编译耗时:

代码语言:javascript
复制
0.20ms  test.swift:17:16
1.82ms  test.swift:18:12
6.35ms  test.swift:19:8
0.11ms  test.swift:22:5
0.02ms  test.swift:24:10
0.02ms  test.swift:30:16
...

例如

代码语言:javascript
复制
xcodebuild -project 'Kickstarter.xcodeproj' \
-scheme 'Kickstarter-iOS' \
-configuration 'Debug' \
-sdk 'iphonesimulator' \
clean build \
OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-expression-type-checking \
    -Xfrontend -debug-time-function-bodies" |
  grep -o "^\d*.\d*ms\t[^$]*$" |
  awk '!visited[$0]++' |
  sed -e "s|$(pwd)/||" |
  sort -rn |
  head -5

16226.04ms Library/Styles/UpdateDraftStyles.swift:31:3
10551.24ms Kickstarter-iOS/Views/RewardCardContainerView.swift:171:16 instance method configureBaseGradientView()
10547.41ms Kickstarter-iOS/Views/RewardCardContainerView.swift:172:7
8639.30ms Kickstarter-iOS/Views/Controllers/AddNewCardViewController.swift:396:67
8233.27ms KsApi/models/templates/ProjectTemplates.swift:94:5

后续小菜还会输出 Swift 编译耗时优化的文章,敬请期待。

BuildTimeAnalyzer

BuildTimeAnalyzer[3] 是一款开源工具,使用很简单。其本质还是利用 Swift 编译器的诊断选项将耗时部分输出出来。

更多阅读

  • Xcode Build Time Optimization 1[4]
  • Xcode Build Time Optimization 2[5]

参考资料

[1]

XCLogParser: https://github.com/spotify/XCLogParser

[2]

Swift 编译器性能: https://github.com/apple/swift/blob/main/docs/CompilerPerformance.md#diagnostic-options

[3]

BuildTimeAnalyzer: https://github.com/RobertGummesson/BuildTimeAnalyzer-for-Xcode

[4]

Xcode Build Time Optimization 1: https://www.onswiftwings.com/posts/build-time-optimization-part1/

[5]

Xcode Build Time Optimization 2: https://www.onswiftwings.com/posts/build-time-optimization-part2/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-04-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小菜与老鸟 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Xcode 编译疾如风-1.如何排查编译耗时问题
    • ShowBuildOperationDuration
      • Build With Timing Summary
        • XCLogParser
          • Swift 代码编译耗时分析
            • 类型检查警告
            • 编译器诊断选项
            • BuildTimeAnalyzer
          • 更多阅读
            • 参考资料
        相关产品与服务
        命令行工具
        腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档