LINQ和Visual Studio 2010内存使用情况

时间:2010-09-20 14:48:30

标签: c# linq visual-studio-2010

我创建了一个LINQ查询,创建一个主组,然后创建两个嵌套组。在最后一个嵌套中,还有一个简单的OrderBy。我遇到的问题是在编写查询或尝试编辑它时,视觉工作室内存消耗天空火箭到~500MB并且正在吃掉50%的CPU,这使得visual studio几秒钟没有响应。如果我注释掉查询,那么visual studio就可以了。所以我的问题是为什么visual studio在设计时为linq查询消耗了这么多内存,认为它有点复杂?

我使用的数据表是10732行长,21列

var results = from p in m_Scores.AsEnumerable()
       group p by p.Field<string>("name") into x
       select new
       {
       Name = x.Key,
       Members = from z in x
             group z by z.Field<string>("id") into zz
             select new
               {
               Id = zz.Key,
               Plots = from a in zz
                   group a by a.Field<string>("foo") into bb
                   select new
                   {
                       Foo = bb.Key,
                       Bars = bb
                   }.Bars.OrderBy(m => m.Field<string>("foo"))
               }
       };

硬件规格:

戴尔Latitude配备2.20GHz双核处理器和4GB内存

1 个答案:

答案 0 :(得分:2)

组和订单的问题在于,他们需要了解整个集合才能执行操作。与min,max,sum,avg等聚合相同的事情。其中一些操作无法询问传递的IEnumerable的真实类型,或者无关紧要,因为它们本质上是“破坏性的”,因此它们必须创建工作副本。当你把这些东西连在一起时,你最终会得到至少两个完整的可枚举副本;由当前方法迭代的前一方法产生的方法,以及由当前方法生成的方法。在查询之外具有引用的可枚举的任何副本(如源可枚举)也保留在内存中,并且已成为孤立的可用数据一直存在,直到GC线程有时间处理并完成它们。对于可枚举的大型源,所有这些都可以在堆上创建大量需求。

此外,在子句中嵌套聚合可以非常快速地使查询变得昂贵。与可以设计“查询计划”的DBMS不同,Linq并不那么聪明。例如,Min()需要迭代整个枚举,以找到指定投影的最小值。当这是Where子句的标准时,一个好的DBMS将在每个上下文中找到该值一次,然后根据需要在后续评估中内联该值。 Linq每次调用时都会运行扩展方法,当你有一个类似enumerable.Where(x =&gt; x.Value == enumerable.Min(x2 =&gt; x2.Value))的条件时,那就是O( N ^ 2) - 复杂度操作只是为了评估滤波器。添加多个级别的分组,Big-O可以轻松达到高多项式复杂度。

通常,您可以通过执行DBMS给出相同查询的优化来减少查询时间。如果可以为查询的整个范围(例如result = source.Where(s=>s.Value == source.Min(x=>x.value)))知道聚合的值,请使用let子句(或外部查询)将其计算为变量,并替换Min()使用别名调用。迭代可枚举两次通常比迭代N ^ 2次便宜,特别是如果可枚举在迭代之间保留在内存中。

此外,在开始分组之前,请确保您的查询顺序尽可能减少样本空间并尽可能便宜。您可能能够对必须昂贵评估的条件进行有根据的猜测,例如Where(s =&gt; s.Value&lt; threshold)。其中(s =&gt; s.Value == source.Min(x =&gt; ; x.Value))或更简洁,Where(s =&gt; s.Value&lt; threshold&amp;&amp; s.Value == source.Min(x =&gt; x.Value))(第二个在C#中工作)因为懒惰的条件评估,但并非所有语言都懒惰地评估)。这将Min()的评估数量减少到符合第一个标准的元素数量。您可以使用现有标准执行相同的操作,只要标准A和B足够独立,A&amp;&amp; amp; B == B&amp;&amp;甲