为什么在C#中使用`list.Sort((x, y) => x – y)`不会发生内存分配。

huangapple go评论102阅读模式
英文:

why list.Sort((x ,y) => x - y) has no memory allocation in C#

问题

以下是您提供的内容的翻译:

C#源代码:
text

  1. public void Sort(Comparison<T> comparison) {
  2. if( comparison == null) {
  3. ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
  4. }
  5. Contract.EndContractBlock();
  6. if( _size > 0) {
  7. IComparer<T> comparer = new Array.FunctorComparer<T>(comparison);
  8. Array.Sort(_items, 0, _size, comparer);
  9. }
  10. }

这行代码:
IComparer comparer = new Array.FunctorComparer(comparison);
显示每次对数组进行排序时,都会创建一个新对象。但当我多次运行它时,我发现根本没有分配。为什么?

这是我的测试代码:

  1. public static void Main(string[] args)
  2. {
  3. List<int> list = new List<int>();
  4. list.Add(1);
  5. list.Add(2);
  6. for (int i = 0; i < 10; ++i)
  7. {
  8. long cnt = GC.GetTotalMemory(false);
  9. list.Sort((x, y) => x - y);
  10. Console.WriteLine(GC.GetTotalMemory(false) - cnt);
  11. }
  12. }
英文:

the C# source code:
text

  1. public void Sort(Comparison&lt;T&gt; comparison) {
  2. if( comparison == null) {
  3. ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
  4. }
  5. Contract.EndContractBlock();
  6. if( _size &gt; 0) {
  7. IComparer&lt;T&gt; comparer = new Array.FunctorComparer&lt;T&gt;(comparison);
  8. Array.Sort(_items, 0, _size, comparer);
  9. }
  10. }

this line
IComparer&lt;T&gt; comparer = new Array.FunctorComparer&lt;T&gt;(comparison);
shows that every time you sort an array, it will create a new object. But when I ran it many times, I found it has no allocation at all.Why?

Here is my test code.

  1. public static void Main(string[] args)
  2. {
  3. List&lt;int&gt; list = new List&lt;int&gt;();
  4. list.Add(1);
  5. list.Add(2);
  6. for (int i = 0; i &lt; 10; ++i)
  7. {
  8. long cnt = GC.GetTotalMemory(false);
  9. list.Sort((x ,y) =&gt; x - y);
  10. Console.WriteLine(GC.GetTotalMemory(false) - cnt);
  11. }
  12. }

答案1

得分: 5

现在不清楚您是否在使用.NET 6/7或.NET Framework 4.x。然而,如果您使用的是.NET Framework 4.x,List&lt;T&gt;.Sort 方法会分配内存。

与直接使用 GC 方法相比,最好使用一个专门设计用于此类操作的基准测试库。我推荐使用 BenchmarkDotNet。例如,像这样的小程序:

  1. using System.Collections.Generic;
  2. using BenchmarkDotNet.Attributes;
  3. using BenchmarkDotNet.Jobs;
  4. using BenchmarkDotNet.Running;
  5. public static class Program
  6. {
  7. public static void Main()
  8. {
  9. BenchmarkRunner.Run&lt;Benchmarks&gt;();
  10. }
  11. }
  12. [MemoryDiagnoser] // 输出内存分配
  13. [SimpleJob(RuntimeMoniker.Net70)]
  14. [SimpleJob(RuntimeMoniker.Net481)]
  15. public class Benchmarks
  16. {
  17. private readonly List&lt;int&gt; _list = new List&lt;int&gt;() { 1, 2 };
  18. [Benchmark]
  19. public void SortList()
  20. {
  21. _list.Sort((x, y) =&gt; x - y);
  22. }
  23. }

将给您输出类似于以下的结果:

Method Job Runtime Mean Error StdDev Gen0 Allocated
SortList .NET 7.0 .NET 7.0 7.989 ns 0.1608 ns 0.1343 ns - -
SortList .NET Framework 4.8.1 .NET Framework 4.8.1 28.208 ns 0.5812 ns 0.9385 ns 0.0038 24 B

现在您可以看到,它确实会根据使用的框架分配 0 字节或 24 字节。

英文:

It's not clear if you are using .NET 6/7 or .NET Framework 4.x. However, the List&lt;T&gt;.Sort method does allocate memory if you are using .NET Framework 4.x.

Instead of directly using the GC methods, it's far better to use a benchmarking library that is specifically designed to do things like this. I recommend BenchmarkDotNet. For example, a small program like this:

  1. using System.Collections.Generic;
  2. using BenchmarkDotNet.Attributes;
  3. using BenchmarkDotNet.Jobs;
  4. using BenchmarkDotNet.Running;
  5. public static class Program
  6. {
  7. public static void Main()
  8. {
  9. BenchmarkRunner.Run&lt;Benchmarks&gt;();
  10. }
  11. }
  12. [MemoryDiagnoser] // output memory allocations
  13. [SimpleJob(RuntimeMoniker.Net70)]
  14. [SimpleJob(RuntimeMoniker.Net481)]
  15. public class Benchmarks
  16. {
  17. private readonly List&lt;int&gt; _list = new List&lt;int&gt;() { 1, 2 };
  18. [Benchmark]
  19. public void SortList()
  20. {
  21. _list.Sort((x, y) =&gt; x - y);
  22. }
  23. }

Will give you output something like this:

Method Job Runtime Mean Error StdDev Gen0 Allocated
SortList .NET 7.0 .NET 7.0 7.989 ns 0.1608 ns 0.1343 ns - -
SortList .NET Framework 4.8.1 .NET Framework 4.8.1 28.208 ns 0.5812 ns 0.9385 ns 0.0038 24 B

Now you can see that it does indeed allocate either 0 bytes or 24 bytes depending on which framework you are using.

huangapple
  • 本文由 发表于 2023年5月17日 19:32:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76271625.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定