【发布时间】:2012-12-11 13:07:04
【问题描述】:
在具有单个字符串属性的简单引用类型的大序列中搜索 Diana 得到了一个有趣的结果。
using System;
using System.Collections.Generic;
using System.Linq;
public class Customer{
public string Name {get;set;}
}
Stopwatch watch = new Stopwatch();
const string diana = "Diana";
while (Console.ReadKey().Key != ConsoleKey.Escape)
{
//Armour with 1000k++ customers. Wow, should be a product with a great success! :)
var customers = (from i in Enumerable.Range(0, 1000000)
select new Customer
{
Name = Guid.NewGuid().ToString()
}).ToList();
customers.Insert(999000, new Customer { Name = diana }); // Putting Diana at the end :)
//1. System.Linq.Enumerable.DefaultOrFirst()
watch.Restart();
customers.FirstOrDefault(c => c.Name == diana);
watch.Stop();
Console.WriteLine("Diana was found in {0} ms with System.Linq.Enumerable.FirstOrDefault().", watch.ElapsedMilliseconds);
//2. System.Collections.Generic.List<T>.Find()
watch.Restart();
customers.Find(c => c.Name == diana);
watch.Stop();
Console.WriteLine("Diana was found in {0} ms with System.Collections.Generic.List<T>.Find().", watch.ElapsedMilliseconds);
}
这是因为 List.Find() 中没有 Enumerator 开销,还是因为这个加上其他原因?
Find() 运行速度几乎是原来的两倍,希望 .Net 团队将来不会将其标记为过时。
【问题讨论】:
-
在
FirstOrDefault之前尝试计时Find()。那么结果如何呢? -
@Oded 做到了。完全相同的。我还按顺序运行了两次 FirstOrDefault,但仍然是相同的 23-24 毫秒(在我的 iCore5 上)。看起来它没有缓存。
-
有趣。性能是否与列表大小成线性关系(FirstOrDefault 是否总是其他列表大小的两倍,或者使用 Linq 是否有固定的 10 毫秒成本)?
-
在 Mono 上甚至更多:戴安娜在 30 毫秒内通过 System.Collections.Generic.List
.Find() 被发现。使用 System.Linq.Enumerable.FirstOrDefault() 在 176 毫秒内找到戴安娜。 -
FirstOrDefault的每个项目间接调用三个,Find的间接调用一个。
标签: c# .net performance linq