在LINQ结果上将IEnumberable 转换为List ,导致巨大的性能损失
在LINQ结果上你喜欢这样:
var result = from x in Items select x; List list = result.ToList();
但是, ToList
真的很慢,是否会使列表变得可变,因此转换速度很慢?
在大多数情况下,我可以设法让我的IEnumerable
或Paralell.DistinctQuery
但现在我想将项目绑定到DataGridView,因此我需要作为其他东西而不是IEnumerable
,关于如何获得ToList或任何性能的建议替换?
在IEnumerable
中的10个百万记录中, .ToList
大约需要6秒钟。
.ToList()
比什么慢?
如果你在比较
var result = from x in Items select x; List list = result.ToList ();
至
var result = from x in Items select x;
你应该注意,由于查询被懒惰地评估,第一行根本没有做太多。 它不会检索任何记录。 延迟执行使得这种比较完全不公平 。
这是因为LINQ喜欢懒惰并尽可能少地工作。 这一行:
var result = from x in Items select x;
尽管您选择了名称,但实际上并不是结果,它只是一个查询对象。 它不会获取任何数据。
List list = result.ToList ();
现在你实际上已经请求了结果,因此它必须从源获取数据并复制它。 ToList保证复制。
考虑到这一点,第二行比第一行慢得多并不奇怪。
不,它不会创建需要时间的列表,它正在获取需要时间的数据。
您的第一个代码行实际上并不获取数据,它只设置一个能够获取数据的IEnumerable。 当你调用ToList方法它实际上将获得所有数据时,这就是所有执行时间都在第二行的原因。
您还应该考虑在网格中有一千万行是否有用。 没有用户会查看所有行,因此实际上并没有任何意义。 也许你应该提供一种在获取任何数据之前过滤结果的方法。
我认为这是因为内存重新分配: ToList
事先无法知道集合的大小,因此它可以分配足够的存储空间来保存所有项目。 因此,它必须在List
增长时重新分配。
如果您可以估计结果集的大小,使用List
构造函数重载预分配足够的元素,然后手动向其添加项目会快得多。