Bất kỳ ai biết bất kỳ sự khác biệt về tốc độ nào giữa Địa điểm và Tìm kiếm trên danh sách. Tôi biết đâu là một phần của IEnumerable và FindAll là một phần của Danh sách, tôi chỉ tò mò những gì nhanh hơn.C# FindAll VS Tốc độ ở đâu
Trả lời
Phương thức FindAll của lớp <T> thực sự tạo đối tượng danh sách mới và thêm kết quả vào đối tượng đó. Phương pháp mở rộng ở đâu cho IEnumerable <T> sẽ đơn giản lặp qua danh sách hiện có và đưa ra một liệt kê các kết quả phù hợp mà không tạo hoặc thêm bất kỳ thứ gì (ngoài chính điều tra viên.)
Cho một bộ nhỏ, hai khả năng thực hiện tương đương. Tuy nhiên, với một tập lớn hơn, Trường hợp sẽ hoạt động tốt hơn FindAll, vì Danh sách mới được tạo để chứa kết quả sẽ phải phát triển động để chứa các kết quả bổ sung. Việc sử dụng bộ nhớ FindAll cũng sẽ bắt đầu tăng theo cấp số nhân khi số lượng kết quả phù hợp tăng lên, ở đâu khi có mức sử dụng bộ nhớ tối thiểu liên tục (trong và của chính nó ... loại trừ bất cứ điều gì bạn làm với kết quả.)
Trường hợp ngoại lệ là nơi bạn thực sự muốn có danh sách sau đó (có thể bạn cần phải gọi 'Đếm' hoặc thay đổi thành viên, hoặc lặp lại qua nhiều lần). Trong khi 'Where()' đánh bại 'FindAll()', 'FindAll()' beats 'Where(). ToList()'. –
@JonHanna: Lúc đầu, tôi nghĩ rằng tôi đồng ý, tôi thực sự không chắc chắn. Bạn có bất kỳ tài liệu tham khảo chỉ ra một .ToList() là chậm hơn một .indAll()? Gọi .ToList() trên một truy vấn sẽ ** được ** lặp đi lặp lại của enumerable, và do đó nên duy trì hiệu quả bộ nhớ của nó. Không chỉ vậy, một số triển khai nội bộ nhất định của nơi lặp có thể tạo danh sách chính xác kích thước (cấp phát bộ nhớ) lên phía trước, vượt trội hơn FindAll trong các trường hợp như vậy. Tôi không đặc biệt không đồng ý, tuy nhiên nó sẽ là tốt đẹp để có một tài liệu tham khảo vững chắc làm rõ lợi ích FindAlls. – jrista
Câu trả lời này đã sai. Xem @Wiory, người đã thực sự quan tâm đến việc đo lường. –
.FindAll()
nên được nhanh hơn, nó tận dụng lợi thế của đã biết kích thước của danh sách và looping thông qua mảng nội bộ với một vòng lặp đơn giản for
. .Where()
phải kích hoạt một điều tra viên (một lớp khung kín được gọi là WhereIterator
trong trường hợp này) và làm cùng một công việc theo một cách ít cụ thể hơn.
Hãy nhớ rằng, .Where() được liệt kê, không chủ động tạo Danh sách trong bộ nhớ và điền vào. Nó giống như một dòng, do đó, việc sử dụng bộ nhớ trên một cái gì đó rất lớn có thể có một sự khác biệt đáng kể. Ngoài ra, bạn có thể bắt đầu sử dụng kết quả theo kiểu song song nhanh hơn nhiều bằng cách sử dụng ở đó .Where() cách tiếp cận trong 4.0.
Bộ chuyển đổi vị trí số, thay vì bộ biến tần, được sử dụng thực sự trừ khi bạn liên quan đến chỉ mục trong mệnh đề where. WhereEnumerableIterator là hiệu quả hơn đáng kể so với WhereIterator. Trong trường hợp của Danh sách
Trong trường hợp gọi trên một Array hoặc List
@jrista - Tôi ** hoàn toàn ** bỏ lỡ ngăn xếp trường hợp trong '.Trường hợp() 'quá tải trở lại những người, cảm ơn! Nhìn qua đoạn mã đó tôi đồng ý, .Tại sao nên có, ở mức tồi tệ nhất, hiệu suất ngang nhau nhưng hầu như luôn luôn tốt hơn. Ngoài ra, SO sẽ vô ích nếu không dành cho những người dành thêm thời gian để giáo dục người khác, ví dụ: bạn và những nhận xét này, +1 để dạy tôi điều gì đó. –
Where
là nhiều, nhanh hơn nhiều so với FindAll
. Bất kể danh sách lớn đến mức nào, Where
sẽ mất khoảng thời gian chính xác.
Tất nhiên Where
chỉ cần tạo truy vấn. Nó không thực sự làm bất cứ điều gì, không giống như FindAll
mà không tạo ra một danh sách.
Điều này có thể đúng về mặt kỹ thuật, nhưng tôi nghĩ rõ ràng là OP hỏi về hiệu suất trong ngữ cảnh thực sự liệt kê kết quả, chứ không phải là phương thức khỏa thân gọi chính nó. –
Câu trả lời từ jrista làm cho các giác quan. Tuy nhiên, danh sách mới thêm các đối tượng tương tự, do đó chỉ tăng trưởng với tham chiếu đến các đối tượng hiện có, không nên chậm. Miễn là 3.5/LINQ mở rộng có thể, ở đâu tốt hơn anyway. FindAll có ý nghĩa hơn nhiều khi bị giới hạn với 2.0
FindAll rõ ràng là chậm hơn ở đâu, bởi vì nó cần tạo danh sách mới.
Dù sao, tôi nghĩ bạn thực sự nên xem xét Jon Hanna bình luận - có thể bạn sẽ cần phải làm một số hoạt động trên kết quả của bạn và danh sách sẽ hữu ích hơn IEnumerable trong nhiều trường hợp.
Tôi đã viết thử nghiệm nhỏ, chỉ cần dán nó vào dự án Ứng dụng giao diện điều khiển. Nó đo thời gian/ticks của: thực hiện chức năng, hoạt động trên bộ sưu tập kết quả (để có được perf. Của sử dụng 'thực', và để chắc chắn rằng trình biên dịch sẽ không tối ưu hóa dữ liệu không sử dụng vv - Tôi mới đến C# và không biết làm thế nào nó hoạt động được nêu ra, xin lỗi).
Lưu ý: mọi hàm được đo trừ Trường hợpIENumerable() tạo Danh sách các phần tử mới. Tôi có thể làm một cái gì đó sai, nhưng rõ ràng lặp IEnumerable mất nhiều thời gian hơn so với danh sách lặp.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace Tests
{
public class Dummy
{
public int Val;
public Dummy(int val)
{
Val = val;
}
}
public class WhereOrFindAll
{
const int ElCount = 20000000;
const int FilterVal =1000;
const int MaxVal = 2000;
const bool CheckSum = true; // Checks sum of elements in list of resutls
static List<Dummy> list = new List<Dummy>();
public delegate void FuncToTest();
public static long TestTicks(FuncToTest function, string msg)
{
Stopwatch watch = new Stopwatch();
watch.Start();
function();
watch.Stop();
Console.Write("\r\n"+msg + "\t ticks: " + (watch.ElapsedTicks));
return watch.ElapsedTicks;
}
static void Check(List<Dummy> list)
{
if (!CheckSum) return;
Stopwatch watch = new Stopwatch();
watch.Start();
long res=0;
int count = list.Count;
for (int i = 0; i < count; i++) res += list[i].Val;
for (int i = 0; i < count; i++) res -= (long)(list[i].Val * 0.3);
watch.Stop();
Console.Write("\r\n\nCheck sum: " + res.ToString() + "\t iteration ticks: " + watch.ElapsedTicks);
}
static void Check(IEnumerable<Dummy> ieNumerable)
{
if (!CheckSum) return;
Stopwatch watch = new Stopwatch();
watch.Start();
IEnumerator<Dummy> ieNumerator = ieNumerable.GetEnumerator();
long res = 0;
while (ieNumerator.MoveNext()) res += ieNumerator.Current.Val;
ieNumerator=ieNumerable.GetEnumerator();
while (ieNumerator.MoveNext()) res -= (long)(ieNumerator.Current.Val * 0.3);
watch.Stop();
Console.Write("\r\n\nCheck sum: " + res.ToString() + "\t iteration ticks :" + watch.ElapsedTicks);
}
static void Generate()
{
if (list.Count > 0)
return;
var rand = new Random();
for (int i = 0; i < ElCount; i++)
list.Add(new Dummy(rand.Next(MaxVal)));
}
static void For()
{
List<Dummy> resList = new List<Dummy>();
int count = list.Count;
for (int i = 0; i < count; i++)
{
if (list[i].Val < FilterVal)
resList.Add(list[i]);
}
Check(resList);
}
static void Foreach()
{
List<Dummy> resList = new List<Dummy>();
int count = list.Count;
foreach (Dummy dummy in list)
{
if (dummy.Val < FilterVal)
resList.Add(dummy);
}
Check(resList);
}
static void WhereToList()
{
List<Dummy> resList = list.Where(x => x.Val < FilterVal).ToList<Dummy>();
Check(resList);
}
static void WhereIEnumerable()
{
Stopwatch watch = new Stopwatch();
IEnumerable<Dummy> iEnumerable = list.Where(x => x.Val < FilterVal);
Check(iEnumerable);
}
static void FindAll()
{
List<Dummy> resList = list.FindAll(x => x.Val < FilterVal);
Check(resList);
}
public static void Run()
{
Generate();
long[] ticks = { 0, 0, 0, 0, 0 };
for (int i = 0; i < 10; i++)
{
ticks[0] += TestTicks(For, "For \t\t");
ticks[1] += TestTicks(Foreach, "Foreach \t");
ticks[2] += TestTicks(WhereToList, "Where to list \t");
ticks[3] += TestTicks(WhereIEnumerable, "Where Ienum \t");
ticks[4] += TestTicks(FindAll, "FindAll \t");
Console.Write("\r\n---------------");
}
for (int i = 0; i < 5; i++)
Console.Write("\r\n"+ticks[i].ToString());
}
}
class Program
{
static void Main(string[] args)
{
WhereOrFindAll.Run();
Console.Read();
}
}
}
Kết quả (ticks) - Checksum kích hoạt (một số hoạt động trên kết quả), phương thức: phát hành mà không cần gỡ lỗi (Ctrl + F5):
- 16222276 (cho -> list)
- 17151121 (foreach -> danh sách)
- 4741494 (nơi -> danh sách)
- 27122285 (nơi -> ienum)
- 18 821.571 (findall -> danh sách)
checksum vô hiệu hóa (không sử dụng trở lại danh sách ở tất cả):
- 10885004 (cho -> danh sách)
- 11221888 (foreach -> list)
- 18688433 (nơi -> danh sách)
- 1075 (nơi -> ienum)
- 13720243 (findall -> list)
Kết quả của bạn có thể khác đôi chút, để có được kết quả thực, bạn cần lặp lại nhiều hơn.
kiểm tra của bạn là tốt. Chúng cho thấy cơ chế LINQ chậm hơn so với hoạt động trực tiếp trên danh sách. Không ngạc nhiên. "1075 (where -> ienum)" của bạn sai ở chỗ sử dụng một nơi mà không đi qua các yếu tố kết quả sẽ không bao giờ thực sự thực hiện một nơi! –
Xin lỗi Carlo, nhưng anh ta gọi phương thức "Check()" của anh ta ngay cả ở nơi thực hiện. Kiểm tra() lặp lại tất cả các bộ sưu tập, vì vậy kết quả của mình là hoàn toàn hợp lệ. Kết quả là, điều đó cũng làm cho câu trả lời của tôi đúng ... câu trả lời mà bạn gọi là "sai lầm". – jrista
- 1. Đặt tốc độ quạt ở C#
- 2. So sánh tốc độ Matlab vs C++ trong mã này
- 3. C# 4.0 Động vs Expando ... chúng phù hợp ở đâu?
- 4. localhost vs LAN: chênh lệch tốc độ?
- 5. Silverlight Speex phát ở tốc độ nhanh
- 6. UIScrollView scrollRectToVisible ở tốc độ tùy chỉnh
- 7. C++ và C# tốc độ so sánh
- 8. VS 2010 Debugging - Trình hiển thị ở đâu
- 9. C# Array.FindAllIndexOf mà FindAll IndexOf
- 10. Từ điển Python vs Nếu Tốc độ Tuyên bố
- 11. cách cải thiện tốc độ khởi chạy ứng dụng C++
- 12. pre-increment vs post-increment - cho vòng lặp tốc độ
- 13. CROSS APPLY vs chênh lệch tốc độ OUTER ÁP DỤNG
- 14. Tốc độ JQuery và tốc độ javascript
- 15. C++ Vector tại/[] tốc độ khai thác
- 16. Cập nhật QTableView hiệu quả ở tốc độ cao
- 17. Tăng tốc độ tạo bảng MySQL ở Django?
- 18. CSS nhiều nền di chuyển ở tốc độ khác nhau
- 19. Locale.SPANISH ở đâu?
- 20. Chạy mã C# được biên dịch động ở tốc độ gốc ... như thế nào?
- 21. gif động vs video vs canvas - cho tốc độ và kích thước tệp
- 22. Làm cách nào để tăng tốc độ khung hình của tôi ở tốc độ 60 khung hình/giây trong Java?
- 23. "ListViewItemPlaceholderBackgroundThemeBrush" nằm ở đâu?
- 24. chuỗi Javascript tốc độ nối
- 25. Chế độ xem 3D trong Firefox firebug ở đâu?
- 26. MonoTouch: Frame.Origin ở đâu?
- 27. Tốc độ AVAudioPlayer
- 28. Job.setOutputKeyClass và job.setOutputReduceClass ở đâu?
- 29. Boost.Process ở đâu?
- 30. Kết hợp chuỗi tốc độ cao trong C#
bản sao có thể có của [FindAll vs Where extension-method] (http://stackoverflow.com/questions/1531702/findall-vs-where-extension-method) –