这个问题不是要找出谁保留了特定对象,而是查看分析器中显示的有过多保留/释放调用的代码段,并找出哪些对象负责。
我有一个 Swift 应用程序,在初始移植后,90% 的时间都花在保留/释放代码上。经过大量重组以避免引用对象后,我已将其降低到大约 25% - 但剩下的部分很难归因。我可以看到它的给定 block 来自使用探查器的给定代码部分,但有时我看不到该代码中应该(据我理解)导致保留/释放的任何内容。我花时间查看两个 Instruments 中的汇编代码(工作时使用并排 View )以及 otool -tvV 的输出,有时还查看保留/释放调用的接近程度一个可识别的部分给了我关于正在发生的事情的提示。我什至在一些地方插入了虚拟方法调用,只是为了让我更好地处理代码中的位置,并关闭优化以限制代码重新排序等。但在很多情况下,我似乎必须将代码追溯到跟踪分支并弄清楚堆栈上有什么,以便理解调用,我对 x86 不够熟悉,不知道这是否实用。 (我将在 Instruments 中添加几个 assembly View 的屏幕截图以及一些 otool 输出以供下面引用)。
我的问题是 - 我还能做什么来调试/检查/归因这些看似过多的保留/释放调用到特定代码?我还可以在 Instruments 中执行其他操作来计算这些调用吗?我已经尝试过分配 View 并打开了引用计数选项,但它似乎没有给我任何新信息(我实际上不确定它做了什么)。或者,如果我更加努力地解释程序集,我是否应该能够弄清楚它保留了哪些对象?在这方面我还应该了解其他工具或技巧吗?
编辑:下面关于单步进入程序集的 Rob 信息正是我所寻找的。我还发现在 XCode 中的 lib 保留/释放调用上设置符号断点并将堆栈上的项目(使用 Rob 建议的“p (id)$rdi”)记录到控制台以便获得粗略的计数很有用。进行了多少次调用,而不是检查每个调用。
最佳答案
您绝对应该关注汇编输出。我发现有两个 View 最有用:“仪器” View 和“assembly ”助理编辑器。问题是 Swift 目前不支持 Assembly 助理编辑器(我通常在 ObjC 中做这种事情),所以我们会接受您的投诉。
看起来您已经在使用调试程序集 View ,它提供了一些不错的符号并且很有用,因为您可以单步执行代码并希望看到它如何映射到程序集。我还找到Hopper很有用,因为它可以给出更多符号。一旦在某个区域中有足够的“独特”函数调用,您通常可以开始缩小程序集映射回源的方式。
我使用的另一个工具是进入保留桥并查看正在传递的对象。为此,指令单步 (^F7) 进入对 swift_bridgeObjectRetain
的调用。 。此时,您可以调用:
p (id)$rdi
它应该至少打印出一些关于正在传递的内容的类型信息( $rdi
在 x86_64 上是正确的,这就是您似乎正在使用的)。我并不总是很幸运地提取更多信息。这取决于那里到底是什么。例如,有时是 ContiguousArrayStorage<Swift.CVarArgType>
,我碰巧了解到这通常意味着它是 NSArray
。我确信 LLDB 方面更好的专家可以更深入地研究,但这通常至少能让我处于正确的大概范围。
(顺便说一句,我不知道为什么我不能在跳转到 p (id)$rdi
之前调用 bridgeObjectRetain
,但它给我带来了奇怪的类型错误。我必须进入该函数打电话。)
希望我有更多。在我看来,Swift 工具链还没有 catch ObjC 工具链在跟踪此类内容方面的水平。
关于performance - 如何使用仪器或查看组件确定 ARC 保留哪些对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31767177/