Tôi biết sự khác biệt giữa IQueryable và IEnumerable, và tôi biết rằng các bộ sưu tập được Linq To Objects hỗ trợ thông qua giao diện IEnumerable.Tại sao IQueryable hai lần nhanh hơn IEnumerable khi sử dụng LINQ To Objects
Câu hỏi của tôi là các truy vấn được thực hiện nhanh gấp hai lần khi bộ sưu tập được chuyển đổi thành một IQueryable.
Hãy l là một đối tượng điền kiểu Danh sách, sau đó một truy vấn LINQ là thời gian nhanh gấp hai lần nếu danh sách l được chuyển đổi thành một IQueryable qua l.AsQueryable().
Tôi đã viết một bài kiểm tra đơn giản với VS2010SP1 và .NET 4.0 thể hiện này:
private void Test()
{
const int numTests = 1;
const int size = 1000 * 1000;
var l = new List<int>();
var resTimesEnumerable = new List<long>();
var resTimesQueryable = new List<long>();
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
for (int x=0; x<size; x++)
{
l.Add(x);
}
Console.WriteLine("Testdata size: {0} numbers", size);
Console.WriteLine("Testdata iterations: {0}", numTests);
for (int n = 0; n < numTests; n++)
{
sw.Restart();
var result = from i in l.AsEnumerable() where (i % 10) == 0 && (i % 3) != 0 select i;
result.ToList();
sw.Stop();
resTimesEnumerable.Add(sw.ElapsedMilliseconds);
}
Console.WriteLine("TestEnumerable");
Console.WriteLine(" Min: {0}", Enumerable.Min(resTimesEnumerable));
Console.WriteLine(" Max: {0}", Enumerable.Max(resTimesEnumerable));
Console.WriteLine(" Avg: {0}", Enumerable.Average(resTimesEnumerable));
for (int n = 0; n < numTests; n++)
{
sw.Restart();
var result = from i in l.AsQueryable() where (i % 10) == 0 && (i % 3) != 0 select i;
result.ToList();
sw.Stop();
resTimesQueryable.Add(sw.ElapsedMilliseconds);
}
Console.WriteLine("TestQuerable");
Console.WriteLine(" Min: {0}", Enumerable.Min(resTimesQueryable));
Console.WriteLine(" Max: {0}", Enumerable.Max(resTimesQueryable));
Console.WriteLine(" Avg: {0}", Enumerable.Average(resTimesQueryable));
}
Chạy thử nghiệm này (với ý numTests == 1 đến 10) sẽ cho kết quả như sau:
Testdata size: 1000000 numbers
Testdata iterations: 1
TestEnumerable
Min: 44
Max: 44
Avg: 44
TestQuerable
Min: 37
Max: 37
Avg: 37
Testdata size: 1000000 numbers
Testdata iterations: 10
TestEnumerable
Min: 22
Max: 29
Avg: 23,9
TestQuerable
Min: 12
Max: 22
Avg: 13,9
Lặp lại phép thử nhưng chuyển đổi thứ tự (tức là đo IQuerable đầu tiên và sau đó là IEnumerable) sẽ cho kết quả differenct!
Testdata size: 1000000 numbers
Testdata iterations: 1
TestQuerable
Min: 75
Max: 75
Avg: 75
TestEnumerable
Min: 25
Max: 25
Avg: 25
Testdata size: 1000000 numbers
Testdata iterations: 10
TestQuerable
Min: 12
Max: 28
Avg: 14
TestEnumerable
Min: 22
Max: 26
Avg: 23,4
Dưới đây là những câu hỏi của tôi:
- Tôi đang làm gì sai?
- Tại sao IEnumerable nhanh hơn nếu thử nghiệm được thực hiện sau khi thử nghiệm IQueryable?
- Tại sao là IQueryable nhanh hơn khi không. chạy thử nghiệm được tăng lên?
- Có hình phạt liên quan đến việc sử dụng IQueryable thay vì IEnumerable?
Tôi hỏi những câu hỏi này vì tôi đã tự hỏi nên sử dụng cái nào để giao diện Kho lưu trữ của mình. Ngay bây giờ họ truy vấn bộ sưu tập trong bộ nhớ (LINQ to Objects), nhưng trong tương lai, có thể là nguồn dữ liệu SQL. Nếu tôi thiết kế các lớp lưu trữ ngay bây giờ với IQueryable Tôi có thể chuyển đổi dễ dàng về sau sang LINQ to SQL. Tuy nhiên nếu có một hình phạt hiệu suất được invloved sau đó gắn bó với IEnumerable trong khi không có SQL tham gia có vẻ là khôn ngoan hơn.
Bạn không chỉ định nếu bạn đang xây dựng trong chế độ phát hành hoặc gỡ lỗi, và bạn không phải là "mồi" các chức năng đầu tiên để bạn có thể nhìn thấy tiếng ồn jitter. (Tôi nghĩ). Về lâu dài, sự khác biệt của một vài ms trên 10.000.000 lần lặp lại không thực sự có vẻ như là một vấn đề lớn. – asawyer
Tôi đang xây dựng ở chế độ gỡ lỗi. Chuyển sang chế độ phát hành và thêm chạy "khởi tạo" (tức là thực thi và thực hiện từng truy vấn một lần) đã trợ giúp: Bây giờ mã ** IEnumerable ** thực thi nhanh hơn một chút so với mã ** IQueryable ** (11ms so với 12ms). Và đó là chính xác những gì tôi mong đợi. Vì vậy, mã thử nghiệm của tôi đã bị lỗi. Cảm ơn các gợi ý! – rbu
"Tôi có thể không chuyển đổi sau này sang LINQ to SQL" ... Tôi rất muốn nghe cách nó hoạt động cho bạn. –