c# - 是什么减慢了简单集合转换的速度

标签 c# arrays collections foreach ienumerable

我有一个简单的 while 循环

IEnumerable<Foo> collection;
while (!bc.IsCompleted)
{
   collection = bc.Take();
}

bc 是 BlockingCollection<IEnumerable<Foo>> 。 bc 包含 9 个 IEnumerable 集合,总共 260 万个 Foo 对象。该循环在我的机器上运行大约需要 640 毫秒。一旦我在 while 循环中的 Take() 之后添加 foreach 循环,运行时间就会激增至 2400 毫秒。

foreach(Foo foo in collection)
{
}

在我单独设置的 List 或 Foo[] 或 IEnumerable 中迭代超过 260 万个元素,花费了大约 54 毫秒。

如果我不使用 foreach 循环,而是简单地添加一个集合转换,例如

,也会发生同样的情况
List<Foo> fooList = collection.ToList();

Foo[] fooArray = collection.ToArray();

执行时间突然也超过了 2000 毫秒。

怎么会这样呢?我完全没有解释或可能的原因。谁能指出我在这里缺少的东西?速度减慢不可能是由锁定/阻塞引起的,因为我没有改变在比较之间访问 BlockingCollection 的方式。

感谢您的任何意见。

最佳答案

与其他 LINQ 方法一样(我猜您正在使用 LINQ 的方法),此方法适用于延迟执行:

This method is implemented by using deferred execution. The immediate return value is an object that stores all the information that is required to perform the action. The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach in Visual C# or For Each in Visual Basic

这意味着,如果您不添加 foreach 循环的 ToList() 调用,则对 Take 的唯一调用不会真正产生任何结果,并且仅当您使用迭代器(foreach/tolist)时才会带来实际结果,因此存在性能差异。

与仅迭代列表的比较可能无法提供准确的结果;它不是对 List(foo) 的迭代需要时间,它可能是从您正在使用的阻塞集合中选择元素,这会减慢一切。
MSDN声称在 BlockingCollection 上使用常规 foreach (这可能是当您使用 LINQ 提供的 Take 时发生的情况,在本例中它适用于 IEunmerable)使用底层集合的 snashop,这肯定会减慢对大型集合的处理。

关于c# - 是什么减慢了简单集合转换的速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10783362/

相关文章:

c# - 在给定 IEnumerable 和成员数据类型的情况下创建通用 IEnumerable<T>

php - 正确格式化 JSON 文件

java.lang.ClassCastException : com. MyComp.model.Image 无法转换为 java.lang.Comparable

java - ArrayList 根据对象属性排序

java - HashSet 和多线程

c# - 跟踪为类和子类创建的实例总数

c# - 处理 ASP.NET 空 Web 应用程序上的所有请求

c# - Visual Studio 在发布时将 .dll 复制到 Bin 文件夹

python - 从 numpy 数组中获取给定半径内的值

java - 如果一个数组中的值不包含在另一个数组中,如何返回 false?