【发布时间】:2023-04-02 16:21:01
【问题描述】:
我在代码中遇到了一个相当愚蠢的性能问题。经过一个小的调查,我发现我用来转换我的通用列表的 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 方法(如果它不在容器的继承行中),因为我会立即遇到性能问题
“在邪恶力量高涨的黑暗时刻避开荒野”
【问题讨论】:
-
你知道这两个测试没有给出相同的结果
-
呃,谢谢。你发现了一个错误:)
-
你为什么在这个集合上调用 AsQueryable?这根本不适合这种用途。这会导致您的 LINQ 方法之后期望构建一种不同类型的表达式树,而不是用于简单的集合,而是用于“可查询”的东西......比如数据库表。
-
因为最初我想将它与 BindingList
一起使用,但我发现了我的性能问题。但是对于 LIst 它不应该影响性能,因为 List is IQueryable,所以即使我调用 AsQueryable() 它也必须直接将列表返回为 IQueryable -> linq 必须是执行为表达式树-> 快速。但这不是 -
哦。列表不是 IQueryable,我的错。
标签: performance linq