childNodeWithName在SpriteKit中的表现如何?

What is the performance of childNodeWithName in SpriteKit?

在SpriteKit中,SKNode的方法childNodeWithName:在接收节点的children中搜索具有特定名称的节点。我知道。

但是性能呢?我的意思是,它是如何实现的?

这个问题的可能答案是:

  1. 它的计算复杂度为 O(n),因为它确实遍历了所有 children
  2. 它的计算复杂度为 O(log n) 因为它确实使用了一些索引结构

我问的原因

如果用for循环实现,那么复杂度为O(n)(n为当前节点children的个数)。那么我们应该避免在一些关键点调用它,比如GameScene的update方法。至少当有很多 children.

在优化我的 iOS 游戏几个小​​时后,我相信 childNodeWithName: 的 运行 时间是线性的而不是对数的。

我遇到的情况是: 场景中有 500 个节点,每个节点都有一个唯一的名称(4 个字节的 UUID,我知道这不是最佳做法)。每 100 毫秒我为每个节点调用 childNodeWithName 以从服务器端应用更新。然后,很明显我观察到 fps 意外下降,即使没有来自服务器的更新(这意味着只有 childNodeWithName 被调用并且 return 立即被调用)。

所以我决定用自定义 Set<String> 替换 childNodeWithName 只是为了检查 SKNode 是否包含具有特定名称的节点。它奏效了,fps 下降消失了。

作为半答案,Apple 强烈建议我们 缓存 childNodeWithNameenumerateChildNodesWithName 调用的结果。

参见:

WWDC 2014 - 第 608 节 - 构建 Sprite Kit 游戏的最佳实践,16 分钟大关

含义很明确:无论查找速度有多快table,如果您有经常引用的对象,那么您应该保留对它们的引用。 (尤其是在 60fps 时。)

至于查找机制,这些集合 containers/clusters 是高度优化的,并根据多种因素使用不同的算法。所以我们不能假设 NSDictionary、NSArray、NSSet 或它们的 Swift 变体实际上可以作为散列 tables 或其他任何东西工作。并且,除非另有标记,否则不能假定具有特定的 O(*) 特性。

(Google 对 NS[Collection] 底层实现细节的精彩分析。)

例如http://ciechanowski.me/blog/2014/03/05/exposing-nsmutablearray/