Tôi đang làm một số xét nghiệm thực hiện và nhận thấy rằng một biểu thức LINQ nhưTại sao LINQ .Where (vị ngữ). Đầu tiên() nhanh hơn .First (vị ngữ)?
result = list.First(f => f.Id == i).Property
là chậm hơn so với
result = list.Where(f => f.Id == i).First().Property
Điều này có vẻ phản trực quan. Tôi đã nghĩ rằng biểu thức đầu tiên sẽ nhanh hơn vì nó có thể dừng lặp lại trong danh sách ngay khi vị từ được thỏa mãn, trong khi tôi đã nghĩ rằng biểu thức .Where()
có thể lặp qua toàn bộ danh sách trước khi gọi số .First()
trên tập con kết quả. Ngay cả khi sau này không ngắn mạch nó không nên nhanh hơn bằng cách sử dụng đầu tiên trực tiếp, nhưng nó được.
Dưới đây là hai bài kiểm tra đơn vị thực sự đơn giản minh họa điều này. Khi được biên dịch với tối ưu hóa trên TestWhereAndFirst nhanh hơn khoảng 30% so với TestFirstOnly trên .Net và Silverlight 4. Tôi đã thử làm cho biến vị ngữ trả về nhiều kết quả hơn nhưng sự khác biệt về hiệu suất là như nhau.
Có thể giải thích tại sao .First(fn)
chậm hơn .Where(fn).First()
không? Tôi thấy kết quả trực quan tương tự với số lượt truy cập là .Count(fn)
so với .Where(fn).Count()
.
private const int Range = 50000;
private class Simple
{
public int Id { get; set; }
public int Value { get; set; }
}
[TestMethod()]
public void TestFirstOnly()
{
List<Simple> list = new List<Simple>(Range);
for (int i = Range - 1; i >= 0; --i)
{
list.Add(new Simple { Id = i, Value = 10 });
}
int result = 0;
for (int i = 0; i < Range; ++i)
{
result += list.First(f => f.Id == i).Value;
}
Assert.IsTrue(result > 0);
}
[TestMethod()]
public void TestWhereAndFirst()
{
List<Simple> list = new List<Simple>(Range);
for (int i = Range - 1; i >= 0; --i)
{
list.Add(new Simple { Id = i, Value = 10 });
}
int result = 0;
for (int i = 0; i < Range; ++i)
{
result += list.Where(f => f.Id == i).First().Value;
}
Assert.IsTrue(result > 0);
}
Bạn định thời gian như thế nào? –
Suy nghĩ ban đầu của bạn là sai mặc dù: LINQ làm tính toán lười biếng, vì vậy khi 'First()' được gọi là nó sẽ truy vấn (giá trị trả về) 'Where (...)' cho chỉ một trận đấu và không bao giờ yêu cầu khác. Vì vậy, cùng một số lượng chính xác các yếu tố sẽ được kiểm tra khi bạn gọi 'Đầu tiên (...) '(tức là trực tiếp với một biến vị ngữ). – Jon
Tôi nhận được kết quả tương tự, '.Where(). First()' là 0,21 giây và '.irst()' là 0,37 giây. Đây là một danh sách đơn giản của 'int'. – Ryan