Linq为什么AsQueryable这么慢?

时间:2011-10-14 16:18:07

标签: performance linq

我的代码中遇到了一个相当愚蠢的性能问题。经过一个小小的调查,我发现我用来构建我的通用列表的AsQueryable方法减慢了代码的速度达8000倍。 所以问题是,为什么呢? 这是示例

class Program
{
    static void Main(string[] args)
    {
        var c = new ContainerTest();
        c.FillList();

        var s = Environment.TickCount;
        for (int i = 0; i < 10000; ++i)
        {
            c.TestLinq(true);
        }
        var e = Environment.TickCount;
        Console.WriteLine("TestLinq AsQueryable - {0}", e - s);

        s = Environment.TickCount;
        for (int i = 0; i < 10000; ++i)
        {
            c.TestLinq(false);
        }
        e = Environment.TickCount;
        Console.WriteLine("TestLinq as List - {0}", e - s);

        Console.WriteLine("Press enter to finish");
        Console.ReadLine();
    }
}

class ContainerTest
{
    private readonly List<int> _list = new List<int>();
    private IQueryable<int> _q; 

    public void FillList()
    {
        _list.Clear();
        for (int i = 0; i < 10; ++i)
        {
            _list.Add(i);
        }
        _q = _list.AsQueryable();
    }

    public Tuple<int, int> TestLinq(bool useAsQ)
    {
        var upperBorder = useAsQ ? _q.FirstOrDefault(i => i > 7) : _list.FirstOrDefault(i => i > 7);
        var lowerBorder = useAsQ ? _q.TakeWhile(i => i < 7).LastOrDefault() : _list.TakeWhile(i => i < 7).LastOrDefault();            

        return new Tuple<int, int>(upperBorder, lowerBorder);
    }
}

UPD据我所知,我必须尽可能避免AsQueryable方法(如果它不在容器的继承行中),因为我会立即 性能问题

“当邪恶的力量被提升时,避免在黑暗的时刻停泊”

3 个答案:

答案 0 :(得分:0)

至少使用LINQ with List

手动实现总是比LINQ

更快

修改

你知道两个测试都没有给出相同的结果

答案 1 :(得分:0)

因为AsQueryable返回IQueryable,它对于LINQ标准查询运算符有一组完全不同的扩展方法,用于List之类的内容。

Queryable集合意味着拥有RDBMS或类似内容的后备存储,当您调用IQueryable.FirstOrDefault()而不是{{1}时,您正在构建一个不同的,更复杂的代码表达式树}。

答案 2 :(得分:0)

刚刚遇到同样的问题。

问题是 IQueryable<T>Expression<Func<T, Bool>> 作为参数用于过滤 Where()/FirstOrDefault() 调用 - 而不仅仅是 Func<T, Bool> 预编译委托采用简单的 IEnumerable 对应方法。

这意味着将有一个编译阶段将 Expression 转换为 delegate。而这成本相当高。

现在您需要在循环中使用它(我就是这样做的)?你会遇到一些麻烦...


PS:似乎是 .NET Core/.NET 5 improves this significantly。不幸的是,我们的项目还没有...