【发布时间】:2012-10-22 07:14:08
【问题描述】:
这是对这个优秀问题C# Sort and OrderBy comparison 的跟进。我将使用相同的示例:
List<Person> persons = new List<Person>();
persons.Add(new Person("P005", "Janson"));
persons.Add(new Person("P002", "Aravind"));
persons.Add(new Person("P007", "Kazhal"));
争用的方法有:
persons.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true));
//and
persons.OrderBy(n => n.Name);
首先让我说,我知道没有任何显着的性能差异需要担心。但我很想知道为什么OrderBy 的性能比Sort 好得多。我正在使用@phoog 在原始问题中发布的答案。
private void button1_Click(object sender, EventArgs e)
{
IEnumerable<Person> people;
BenchMark(persons => persons.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true)));
BenchMark(persons => people = persons.OrderBy(n => n.Name));
}
private static Random randomSeed = new Random();
public static string RandomString(int size, bool lowerCase)
{
var sb = new StringBuilder(size);
int start = (lowerCase) ? 97 : 65;
for (int i = 0; i < size; i++)
{
sb.Append((char)(26 * randomSeed.NextDouble() + start));
}
return sb.ToString();
}
private static void BenchMark(Action<List<Person>> action)
{
List<Person> persons = new List<Person>();
for (int i = 0; i < 10000; i++)
{
persons.Add(new Person("P" + i.ToString(), RandomString(5, true)));
}
List<Person> unsortedPersons = new List<Person>(persons);
Stopwatch watch = new Stopwatch();
for (int i = 0; i < 100; i++)
{
watch.Start();
action(persons);
watch.Stop();
persons.Clear();
persons.AddRange(unsortedPersons);
}
MessageBox.Show(watch.Elapsed.TotalMilliseconds.ToString());
}
结果:
Sort() => 3500 ~ 5000 ms
OrderBy() => 0.2 ~ 1.5 ms
尽管我最初测试的列表越小,差异也很大,但随着集合规模的增加,这种差异变得越来越明显。可能是我遗漏了一些理解 .NET 集合的关键,但我的想法是因为Sort 作用于现有的List<T>,与OrderBy 相比,它在处理中的开销(如果有的话)应该更少。在同一个List<T>(在我们的例子中为persons)但必须返回另一个集合IOrderedEnumerable<T>。但OrderBy 的表现仍然要好得多。与IEnumerable<T> 类型相比,List<T> 可能有一定的开销,但Sort 无论如何都会作用于现有列表!此外,看到Linq 方法比现有的.NET 方法运行得更快,我感到很高兴。
原始问题中的所有答案都将Sort 与OrderBy.ToList 进行比较,我认为这会产生一些开销,因此或多或少地表现相同。
可能有哪些实现差异?
编辑:好的,我学到了一些新东西。以下是我确认延迟执行的方式。
private void button1_Click(object sender, EventArgs e)
{
BenchMark(persons =>
{
persons.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true));
foreach (var item in persons)
{
break;
}
});
BenchMark(persons =>
{
IEnumerable<Person> people = persons.OrderBy(n => n.Name);
foreach (var item in people)
{
break;
}
});
}
Sort 运行时间为 4000 - 5000 毫秒,而 OrderBy 运行时间略高于 5000 毫秒。所以确实我的结论是错误的。一旦我开始列举这些收藏品,它们的表现就相当了。我更喜欢OrderBy anyday 的语法:)
编辑 2: 我刚刚发现这与 this one 完全相同。但这里有一个more interesting question about deferred execution in general,虽然不是完全订购。
【问题讨论】:
标签: c# .net linq sorting collections