.net - LINQ 性能 - 延迟执行与立即执行

标签 .net linq performance

我发现有时如果使用 .ToArray() 强制立即执行 LINQ to Objects 查询,其性能可以显着提高,但不太明白为什么。例如,在下面的示例中,函数 Deferred() 的执行速度比函数 Immediate() 慢得多,并且随着 的值呈指数增长limit (也许这两个函数都是指数级的,但是 Immediate() 的执行时间太短了,我无法明确地说)。

public void Deferred()
{
    var all = Range(limit);
    var even = from e in EvenRange(limit) where all.Contains(e) select e;
    var odd = from o in OddRange(limit) where !even.Contains(o) select o;

    var query = from q in odd select q;

    foreach(var i in query) { var j = i+1; }
}

public void Immediate()
{
    var all = Range(limit);
    var even = (from e in EvenRange(limit) where all.Contains(e) select e)
        .ToArray();
    var odd = (from o in OddRange(limit) where !even.Contains(o) select o)
        .ToArray();

    var query = (from q in odd select q).ToArray();

    foreach(var i in query) { var j = i+1; }
}

public static IEnumerable<int> OddRange(int stop)
{
    for (int i = 1; i < stop; i+=2) yield return i;
}

public static IEnumerable<int> EvenRange(int stop)
{
    for (int i = 2; i < stop; i+=2) yield return i;
}

public static IEnumerable<int> Range(int stop)
{
    for (int i = 0; i < stop; ++i) yield return i;
}

是什么导致了这种减速?这只是编译器生成的额外代码,并且每次访问可枚举时都必须运行,还是 Deferred() 也会进入一些额外的循环,从而改变查询的“Big O”复杂性?

最佳答案

据我所知 IEnumerable 不会缓存结果,因此涉及 Even.Contains 的子句(必须检查 Even 的所有元素)强制完全重新枚举 Even,从而显示您注意到的性能行为。在数组或列表中转换偶数应该会在枚举奇数时显示出良好的性能。其他 .NET 语言(例如 F#)包含缓存枚举结果的方法(如果您感兴趣,可以查看 F# 的 Seq.cache 方法)

关于.net - LINQ 性能 - 延迟执行与立即执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/872697/

相关文章:

performance - 当前 CPU 的成本更高 : arithmetic operations or conditionals?

c# - ArrayList 与 C# 中的 List<>

c# - 那里有任何像样的 C# 分析器吗?

c# - 我可以改进嵌入式 C# 上的 "double.IsNaN( x )"函数调用吗?

c# - System.Collections.Generic.Find() 与 Linq.First()

c# - LINQ to Entities 相似代码

ios - 如何让 iOS 上的 tesseract 更快?

c# - MVC 4 Controller 中的异步和等待

C# - 日期/时间格式化

c# - 动态创建属性