我正在Swift中移植一个路径跟踪器(为了好玩(。它使用一个简单的八叉树加速结构,实现为SpatialIndex
类,子节点具有[SpatialIndex?]
属性。我写了一个测试加速度结构的方法,只需找到离某个任意点最近的点。第一种方法是递归的,效果很好。然后,我尝试实现一种基于循环的方法,这种方法也很好,但速度慢了3倍,而且大部分时间都花在了保留/释放调用上。
问题是,我真的不明白为什么它需要比递归方法更多的保留/释放调用,我也不知道如何追踪实际的ARC。在这种情况下,引用计数大约占所花费时间的一半。至少可以说,这似乎有点过分。
当我搜索ARC问题时,我发现的大多是与保留循环相关的东西。我真正想做的是有效地绕过整个系统,因为我知道树的内存布局不会改变。
所以我的问题基本上是:当ARC导致性能问题时,追踪它实际花费的时间参考计数的最佳选择是什么,以及我如何加快它的速度?
您可以使用Unmanaged
类型绕过特定对象的ARC。我没有试过这么多,但我想它会是这样的:
-
在性能关键部分之前,将要跳过ARC的对象包装在
Unmanaged
值中:let unmanagedObj = Unmanaged.passRetained(obj)
-
在关键部分中,传递
Unmanaged
值将不需要引用计数开销。当你需要使用对象时,像这样提取它:let obj = unmanagedObj.takeUnretainedValue()
-
在关键部分之后,释放对象:
unmanagedObj.release()
当然,只有当您控制了需要将对象传递给的函数时,这才有效,因为您必须将它们从获取对象更改为获取Unmanaged
值。我不知道你是不是这样。
也许您可以通过将对象图的不同部分切换到Unmanaged
来找出哪些类型的对象会在代码中造成最大的引用计数开销。