【问题标题】:How to debug slow Swift compile times如何调试缓慢的 Swift 编译时间
【发布时间】:2015-10-03 13:21:56
【问题描述】:

我有一个包含大约 25 个小文件的 Swift SpriteKit 项目。编译这个项目的时间是 30-45 秒!它是没有 ObjC 的纯 Swift。

我在 Report Navigator 中观看了编译,试图找到一个耗时的文件。但是,它并不是真正的单个文件。似乎总是在列表中的 last 文件。但是该文件在编译之间可能会有所不同,并且仍然需要花费所有时间。

最后一个文件之后的步骤是 Merge xxx.swiftmodule,它发生得很快,但我不确定是否因为它紧随其后可能与缓慢有关。

我已经搜索并尝试了各种方法来找到罪魁祸首。我读了这篇文章:Why is Swift compile time so slow? 并尝试了这些方法。我已经使用 CTRL-\ 完成了命令行构建,但没有显示任何有关缓慢的有用信息。

我已经完成了我的项目,寻找类型推断可能会出错的地方,但没有找到太多(真的,如果是这样的话,我希望单个文件是罪魁祸首) .

有没有人有任何其他的建议来追踪这个?来自一个几乎可以立即编译的 Objective-C 项目,这让我发疯。

编辑 我在这方面做了更多的工作,并且包括了构建输出的屏幕截图,并指出了缓慢发生的位置。问题是,如果我注释掉慢速文件中的代码,那么列表中的 before 文件就会变成慢速文件(以前很好)。如果我将该代码注释掉,那么 before 就会变成慢代码,以此类推。

【问题讨论】:

  • 编译还是链接?没有你发布任何日志,我们几乎无法帮助你,除了告诉你 a) 使用 Swift 2.0,b) 等待 Apple 真正发布 Swift 2.0。
  • 键入每个数组和字典 - 不要强迫编译器推断它。我习惯于输入所有内容 - 每个 let 和每个 var - 以降低编译速度(在我的慢速 MacBook Air 上......)
  • 谢谢克劳斯。我会看看抓取一些日志。顺便说一句,我使用的是 Swift 2.0。
  • 如何测量单个文件的编译时间?

标签: ios swift compilation


【解决方案1】:

经过更多的挖掘和调试,我发现了问题所在。事实证明,正如其他帖子所建议的那样,它实际上是 is 类型推断。部分问题是我没有注意到 Report Navigator 中的构建输出显示仍在编译的文件的箭头和已完成的文件的复选标记(我的色盲起了作用)。所以我以为他们都完成了编译,而一个还没有。

无论如何,我在这里阅读了这篇文章:GM release of Xcode 6 compile,并对整个项目进行了命令行构建,它向我展示了问题所在的文件。然后,使用上面提到的 CTRL-\ 方法,我找到了罪魁祸首。

原来这行是问题所在:

ourWindowCopy.position = CGPoint(x: ((26.5 + theXOffset) * self.multiplierWidth) + (4.0 * CGFloat(randomRow) * 2.0 * self.multiplierWidth), y: ((41.0 + theYOffset) * self.multiplierHeight) + (5.75 * CGFloat(randomColumn) * 2.0 * self.multiplierHeight))

我知道这看起来一团糟——我很早就在玩一堆不同的选项,但还没有回去简化。我用这个替换了它(当然会替换文字以及更进一步):

let floatRandomRow = CGFloat(randomRow)
let floatRandomCol = CGFloat(randomColumn)
let pointX: CGFloat = ((26.5 + theXOffset) * self.multiplierWidth) + (4.0 * floatRandomRow * 2.0 * self.multiplierWidth)
let pointY: CGFloat = ((41.0 + theYOffset) * self.multiplierHeight) + (5.75 * floatRandomCol * 2.0 * self.multiplierHeight)

ourWindowCopy.position = CGPoint(x: pointX, y: pointY)

现在编译速度非常快!

我不确定这里是否真的有任何新信息,但我想用一个解决方案来解决这个问题,以防有人遇到它。

【讨论】:

    【解决方案2】:

    在 Swift 编译器中有一个隐藏选项,可以打印出编译器编译每个函数所需的确切时间间隔:-Xfrontend -debug-time-function-bodies

    在终端中简单运行以下命令并分析结果:

    xcodebuild -workspace App.xcworkspace -scheme App clean build OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" | grep [1-9].[0-9]ms | sort -nr > culprits.txt
    

    很棒的 Brian Irace 写了一篇关于它的精彩文章 Profiling your Swift compilation times

    【讨论】:

      【解决方案3】:

      在其他答案的基础上,以下命令很有帮助...

      要查看按构建时间排序的函数列表:

      xcodebuild -workspace [Your Workspace Name].xcworkspace -scheme [Your Build Scheme Name] clean build OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" | grep .[0-9]ms | grep -v ^0.[0-9]ms | sort -nr > culprits.txt
      

      要查看构建时间超过 1 秒的函数的排序列表:

      xcodebuild -workspace [Your Workspace Name].xcworkspace -scheme [Your Build Scheme Name] clean build OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" | grep [1-9].[0-9]ms | sort -nr > culprits.txt
      

      您可以像这样获得方案名称列表(此命令首先运行干净):

      xcodebuild -workspace [Your Workspace Name].xcworkspace -list
      

      关于为什么你的构建时间可能很长的有用文章:

      【讨论】:

      • 如果您使用的是项目 (xcodeproj) 而不是工作区 (xcworkspace),请在上述命令中使用 -project [Your Project Name].xcodeproj 而不是 -workspace [Your Workspace Name].xcworkspace
      • 代替最后的 grep/sort 部分,您可以使用此命令更新最新输出和zsh。它删除重复项,仅输出 100+ 毫秒的重复项:grep -E '^\d{3,}.\d{2}ms' | sort -nr | uniq -u
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-21
      • 2015-12-28
      • 2011-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多