单一呼叫的Linq缓慢

时间:2012-12-03 04:29:50

标签: c# linq optimization

背景:我的游戏正在使用组件系统。我有一个Entity类,其中包含IComponentList<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循环更有效。这是怎么回事?

2 个答案:

答案 0 :(得分:6)

Single的文档说:

  

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

另一方面First

  

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

因此,使用Single,您将遍历整个序列而不使用short circuiting,这就是上面的foreach循环所做的事情。因此,请使用FirstFirstOrDefault代替Single

答案 1 :(得分:1)

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

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

来源: List<T>.Single Method