Câu hỏi liên quan

0 Phiếu
4 Câu trả lời
0 Phiếu
7 Câu trả lời
0 Phiếu
0 Câu trả lời

LINQ hiệu suất tính vs nơi và đếm


0 Phiếu
Đã hỏi 25/5/2016 bởi Nccfetch (720 điểm)
kiểm tra
public class Group
{
   public string Name { get; set; }
}  
:
List<Group> _groups = new List<Group>();
for (int i = 0; i < 10000; i++)
{
    var group = new Group();
    group.Name = i + "asdasdasd";
    _groups.Add(group);
}
Stopwatch _stopwatch2 = new Stopwatch();
_stopwatch2.Start();
foreach (var group in _groups)
{
    var count = _groups.Count(x => x.Name == group.Name);
}
_stopwatch2.Stop();
Console.WriteLine(_stopwatch2.ElapsedMilliseconds);
Stopwatch _stopwatch = new Stopwatch();
_stopwatch.Start();
foreach (var group in _groups)
{
    var count = _groups.Where(x => x.Name == group.Name).Count();
}
_stopwatch.Stop();
Console.WriteLine(_stopwatch.ElapsedMilliseconds);
quả: đầu tiên: 2863, 2185 thứ hai có thể ai đó giải thích tại sao phương pháp tiếp cận đầu tiên là chậm hơn so với lần thứ hai? Thứ hai nên trở về số đếm và gọi truy cập vào nó và lần đầu tiên, chỉ cần gọi số. Phương pháp tiếp cận đầu tiên nên một chút nhanh hơn. EDIT: tôi gỡ bỏ counter danh sách để ngăn chặn bằng cách sử dụng GC và thay đổi để kiểm tra nếu thứ tự có ý nghĩa. Kết quả là gần như giống nhau. EDIT2: vấn đề hiệu suất này không có liên quan chỉ với Count. Nó có liên quan với First(), () FirstOrDefault, Any(), v.v... Nơi + phương pháp là luôn nhanh hơn so với phương pháp.

4 Câu trả lời

0 Phiếu
Đã trả lời 03/6/2016 bởi Runningposch (570 điểm)
Sarge Borsch đã đưa ra câu trả lời đúng trong các ý kiến, nhưng mà không cần giải thích thêm. Các vấn đề nằm với một thực tế rằng bytecode phải được biên dịch để x86 bởi compiler JIT trên chạy đầu tiên. Kết quả là biện pháp của bạn kết hợp cả những gì bạn muốn test và thời gian compilation . Và kể từ khi hầu hết những điều được sử dụng bởi test thứ hai này sẽ có biên soạn trong thời gian đầu tiên test (liệt kê danh sách, tên tài sản getter, vv), người đầu tiên hơn bị ảnh hưởng bởi việc biên soạn. Giải pháp là để làm một "ấm lên": bạn chạy code của bạn một lần mà không thực hiện các biện pháp, thông thường với lặp đi lặp lại chỉ là một, đơn giản chỉ để có nó biên soạn. Sau đó, bạn bắt đầu đồng hồ bấm giờ và chạy nó một lần nữa thật, với lặp đi lặp lại như nhiều như cần thiết để có được một thời gian đủ dài (một thứ hai ví dụ).
0 Phiếu
Đã trả lời 04/6/2016 bởi shilai (180 điểm)
Nó có vẻ với tôi rằng sự khác biệt là trong cách các phần mở rộng Linq được mã hoá. Tôi nghi ngờ Where sử dụng tối ưu hóa trong List<> class để tăng tốc độ hoạt động, nhưng Count chỉ iterates thông qua một IEnumerable<>. Nếu bạn làm quá trình tương tự, nhưng với một IEnumerable, cả hai phương pháp được gần gũi, với Where người hơi chậm.
List<Group> _groups = new List<Group>();
for (int i = 0; i < 10000; i++)
{
    var group = new Group();
    group.Name = i + "asdasdasd";
    _groups.Add(group);
}
IEnumerable<Group> _groupsEnumerable = from g in _groups select g;
Stopwatch _stopwatch2 = new Stopwatch();
_stopwatch2.Start();
foreach (var group in _groups)
{
    var count = _groupsEnumerable.Count(x => x.Name == group.Name);
}
_stopwatch2.Stop();
Console.WriteLine(_stopwatch2.ElapsedMilliseconds);
Stopwatch _stopwatch = new Stopwatch();
_stopwatch.Start();
foreach (var group in _groups)
{
    var count = _groupsEnumerable.Where(x => x.Name == group.Name).Count();
}
_stopwatch.Stop();
Console.WriteLine(_stopwatch.ElapsedMilliseconds);
nơi phương pháp mở rộng. Thông báo trường hợp if (source is List<TSource>):
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    if (predicate == null)
    {
        throw Error.ArgumentNull("predicate");
    }
    if (source is Enumerable.Iterator<TSource>)
    {
        return ((Enumerable.Iterator<TSource>)source).Where(predicate);
    }
    if (source is TSource[])
    {
        return new Enumerable.WhereArrayIterator<TSource>((TSource[])source, predicate);
    }
    if (source is List<TSource>)
    {
        return new Enumerable.WhereListIterator<TSource>((List<TSource>)source, predicate);
    }
    return new Enumerable.WhereEnumerableIterator<TSource>(source, predicate);
}
tính phương pháp. Chỉ cần iterates thông qua IEnumerable:
public static int Count<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    if (predicate == null)
    {
        throw Error.ArgumentNull("predicate");
    }
    int num = 0;
    checked
    {
        foreach (TSource current in source)
        {
            if (predicate(current))
            {
                num++;
            }
        }
        return num;
    }
}
Đã bình luận 06/6/2016 bởi several (180 điểm)
Đo lường của bạn là không chính xác-bạn không làm ấm
0 Phiếu
Đã trả lời 04/6/2016 bởi thisNorse (200 điểm)
Đoán của tôi:. Where() sử dụng đặc biệt " WhereListIterator " để iterate qua các yếu tố, Count() không, như được chỉ ra bởi Wyatt Earp. Điều thú vị là iterator được đánh dấu là "ngenable":
 [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
 public WhereListIterator(List<TSource> source, Func<TSource, bool> predicate)
 {
   this.source = source;
   this.predicate = predicate;
 }
có lẽ điều này có nghĩa là phần "iterator" chạy như là một "không được quản lý mã", trong khi Count() chạy như là một mã số quản lý. Tôi không biết nếu điều đó làm cho cảm giác / làm thế nào để chứng minh điều đó, nhưng đó là 0.2cents của tôi. Ngoài ra, nếu bạn viết lại Count() để chăm sóc của danh sách cẩn thận, bạn có thể làm cho nó cùng / nhanh hơn:
public static class TestExt{
   public static int CountFaster<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
       if (source == null) throw new Exception();
       if (predicate == null) throw new Exception();
       if(source is List<TSource>)
       {
                int finalCount=0;
                var list = (List<TSource>)source;
                var count = list.Count;
                for(var j = 0; j < count; j++){
                    if(predicate(list[j])) 
                        finalCount++;
                }
                return finalCount;
       }

       return source.Count(predicate);
   }
} ngày thử nghiệm của tôi; sau khi tôi đã bắt đầu bằng cách sử dụng CountFaster (), một trong những người được gọi là LATER thắng (vì lạnh-khởi động).
+1 Phiếu
Đã trả lời 04/6/2016 bởi anyone_nell (1,070 điểm)
Đoán của tôi:. Where() sử dụng đặc biệt " WhereListIterator " để iterate qua các yếu tố, Count() không, như được chỉ ra bởi Wyatt Earp. Điều thú vị là iterator được đánh dấu là "ngenable":
 [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
 public WhereListIterator(List<TSource> source, Func<TSource, bool> predicate)
 {
   this.source = source;
   this.predicate = predicate;
 }
có lẽ điều này có nghĩa là phần "iterator" chạy như là một "không được quản lý mã", trong khi Count() chạy như là một mã số quản lý. Tôi không biết nếu điều đó làm cho cảm giác / làm thế nào để chứng minh điều đó, nhưng đó là 0.2cents của tôi. Ngoài ra, nếu bạn viết lại Count() để chăm sóc của danh sách cẩn thận, bạn có thể làm cho nó cùng / nhanh hơn:
public static class TestExt{
   public static int CountFaster<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
       if (source == null) throw new Exception();
       if (predicate == null) throw new Exception();
       if(source is List<TSource>)
       {
                int finalCount=0;
                var list = (List<TSource>)source;
                var count = list.Count;
                for(var j = 0; j < count; j++){
                    if(predicate(list[j])) 
                        finalCount++;
                }
                return finalCount;
       }

       return source.Count(predicate);
   }
} ngày thử nghiệm của tôi; sau khi tôi đã bắt đầu bằng cách sử dụng CountFaster (), một trong những người được gọi là LATER thắng (vì lạnh-khởi động).

ToughDev Q&A là gì?

Trang web hỏi đáp cho các bạn đam mê lập trình, phát triển phần mềm và các vấn đề kỹ thuật khác. Với sự giúp đỡ của bạn, chúng tôi hy vọng sẽ xây dựng thành công một thư viện đầy đủ các câu hỏi và trả lời về tất cả các vấn đề có liên quan đến lập trình!







...