gpt4 book ai didi

c# - 为什么返回 IOrderedEnumerable 的 OrderBy 比 Sort 快得多?

转载 作者:IT王子 更新时间:2023-10-29 04:36:48 24 4
gpt4 key购买 nike

这是对这个优秀问题的跟进 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表现要好得多。 List<T>IEnumerable<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 的语法任何时候:)

编辑 2: 我刚刚发现这与 this one 完全相同.但这里有一个 more interesting question about deferred execution in general虽然不是完全订购。

最佳答案

在这种情况下,OrderBy速度要快得多,因为您实际上并没有执行它。

在您枚举结果之前,查询是延迟的,因此它从未实际进行排序。在您实际枚举结果之前,IOrderedEnumerable<T>不处理输入并进行任何形式的排序。

尝试将基准更改为:

 BenchMark(persons => people = persons.OrderBy(n => n.Name).Count());

Count()调用将强制实际发生排序(因为它需要枚举 IOrderedEnumerable<T> 来生成计数),这应该会显着平衡您的时间。

大多数 LINQ 扩展方法都是这样工作的——直到您枚举它们(通过 Count() 、调用 ToList() 或只是在普通的 foreach 循环中使用它们,等等),它们的影响可以忽略不计,因为它们不' 实际上直接做任何事情,而不是构建可枚举的。其他基准与 OrderBy(...).ToList() 比较的原因是添加ToList()强制 OrderBy完全执行并实际排序结果。

关于c# - 为什么返回 IOrderedEnumerable<T> 的 OrderBy 比 Sort 快得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13181498/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com