追踪Swift中的过度保留/释放



我正在Swift中移植一个路径跟踪器(为了好玩(。它使用一个简单的八叉树加速结构,实现为SpatialIndex类,子节点具有[SpatialIndex?]属性。我写了一个测试加速度结构的方法,只需找到离某个任意点最近的点。第一种方法是递归的,效果很好。然后,我尝试实现一种基于循环的方法,这种方法也很好,但速度慢了3倍,而且大部分时间都花在了保留/释放调用上。

问题是,我真的不明白为什么它需要比递归方法更多的保留/释放调用,我也不知道如何追踪实际的ARC。在这种情况下,引用计数大约占所花费时间的一半。至少可以说,这似乎有点过分。

当我搜索ARC问题时,我发现的大多是与保留循环相关的东西。我真正想做的是有效地绕过整个系统,因为我知道树的内存布局不会改变。

所以我的问题基本上是:当ARC导致性能问题时,追踪它实际花费的时间参考计数的最佳选择是什么,以及我如何加快它的速度?

您可以使用Unmanaged类型绕过特定对象的ARC。我没有试过这么多,但我想它会是这样的:

  1. 在性能关键部分之前,将要跳过ARC的对象包装在Unmanaged值中:

    let unmanagedObj = Unmanaged.passRetained(obj)
    
  2. 在关键部分中,传递Unmanaged值将不需要引用计数开销。当你需要使用对象时,像这样提取它:

    let obj = unmanagedObj.takeUnretainedValue()
    
  3. 在关键部分之后,释放对象:

    unmanagedObj.release()
    

当然,只有当您控制了需要将对象传递给的函数时,这才有效,因为您必须将它们从获取对象更改为获取Unmanaged值。我不知道你是不是这样。

也许您可以通过将对象图的不同部分切换到Unmanaged来找出哪些类型的对象会在代码中造成最大的引用计数开销。

相关内容

  • 没有找到相关文章

最新更新