2

背景:我的游戏使用的是组件系​​统。我有一个Entity类,其中有一个IComponent实例列表List<IComponent>。我目前的实现Entity.GetComponent<T>()是:

return (T)this.components.Single(c => c is T);

添加碰撞检测后,我注意到我的游戏下降到 1FPS。分析显示罪魁祸首就是这个调用(每帧调用 3000 多次)。

除了 3000x,我注意到调用这 300k 次大约需要 2 秒。我将其优化为一个简单的迭代循环:

foreach (IComponent c in this.components) { 
  if (c is T) {
    return (T)c; 
  }
}

return default(T);

这段代码现在运行时间大约为 0.4 秒,这要好一个数量级。

我认为Single会比单个 foreach 循环更有效。这里发生了什么?

4

2 回答 2

6

的文档Single说:

返回序列的唯一元素,如果序列中不完全有一个元素,则抛出异常。

另一方面First

通过指定谓词函数中测试的序列中的第一个元素。

因此,Single在没有 的情况下遍历整个序列short circuiting,这就是foreach上面的循环所做的。所以,使用FirstorFirstOrDefault代替Single.

于 2012-12-03T04:53:15.837 回答
1

Single 遍历整个集合并确保只找到一项。所以你最好的表现总是 O(N)

您的迭代搜索也受到 O(N) 性能的影响,但这是最坏的情况。

来源: List<T>.Single 方法

于 2012-12-03T04:48:33.643 回答