在Swift中追踪过多的保留/释放

时间:2018-07-13 21:32:28

标签: swift automatic-ref-counting

我正在Swift中移植路径跟踪器(出于娱乐目的)。它使用简单的八叉树加速结构,实现为SpatialIndex类,并为子节点提供[SpatialIndex?]属性。我写了一种方法,通过找到任意点的最接近点来测试加速度结构。第一种方法是递归的,并且效果很好。然后,我尝试实现一种基于循环的方法,该方法也可以正常工作,但速度慢了3倍,并且其中大部分时间都花在了保留/释放调用上。

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

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

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

1 个答案:

答案 0 :(得分:0)

您可以使用Unmanaged type绕过特定对象的ARC。我还没有尝试太多,但是我想它看起来像这样:

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

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

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

    unmanagedObj.release()
    

当然,这仅在您控制传递对象所需的功能时才起作用,因为您必须将其从采用对象更改为采用Unmanaged值。我不知道您是否是这种情况。

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