英文:
why list.Sort((x ,y) => x - y) has no memory allocation in C#
问题
以下是您提供的内容的翻译:
C#源代码:
text
public void Sort(Comparison<T> comparison) {
if( comparison == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
}
Contract.EndContractBlock();
if( _size > 0) {
IComparer<T> comparer = new Array.FunctorComparer<T>(comparison);
Array.Sort(_items, 0, _size, comparer);
}
}
这行代码:
IComparer
显示每次对数组进行排序时,都会创建一个新对象。但当我多次运行它时,我发现根本没有分配。为什么?
这是我的测试代码:
public static void Main(string[] args)
{
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
for (int i = 0; i < 10; ++i)
{
long cnt = GC.GetTotalMemory(false);
list.Sort((x, y) => x - y);
Console.WriteLine(GC.GetTotalMemory(false) - cnt);
}
}
英文:
the C# source code:
text
public void Sort(Comparison<T> comparison) {
if( comparison == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
}
Contract.EndContractBlock();
if( _size > 0) {
IComparer<T> comparer = new Array.FunctorComparer<T>(comparison);
Array.Sort(_items, 0, _size, comparer);
}
}
this line
IComparer<T> comparer = new Array.FunctorComparer<T>(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.
public static void Main(string[] args)
{
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
for (int i = 0; i < 10; ++i)
{
long cnt = GC.GetTotalMemory(false);
list.Sort((x ,y) => x - y);
Console.WriteLine(GC.GetTotalMemory(false) - cnt);
}
}
答案1
得分: 5
现在不清楚您是否在使用.NET 6/7或.NET Framework 4.x。然而,如果您使用的是.NET Framework 4.x,List<T>.Sort
方法会分配内存。
与直接使用 GC
方法相比,最好使用一个专门设计用于此类操作的基准测试库。我推荐使用 BenchmarkDotNet。例如,像这样的小程序:
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
public static class Program
{
public static void Main()
{
BenchmarkRunner.Run<Benchmarks>();
}
}
[MemoryDiagnoser] // 输出内存分配
[SimpleJob(RuntimeMoniker.Net70)]
[SimpleJob(RuntimeMoniker.Net481)]
public class Benchmarks
{
private readonly List<int> _list = new List<int>() { 1, 2 };
[Benchmark]
public void SortList()
{
_list.Sort((x, y) => x - y);
}
}
将给您输出类似于以下的结果:
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<T>.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:
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
public static class Program
{
public static void Main()
{
BenchmarkRunner.Run<Benchmarks>();
}
}
[MemoryDiagnoser] // output memory allocations
[SimpleJob(RuntimeMoniker.Net70)]
[SimpleJob(RuntimeMoniker.Net481)]
public class Benchmarks
{
private readonly List<int> _list = new List<int>() { 1, 2 };
[Benchmark]
public void SortList()
{
_list.Sort((x, y) => x - y);
}
}
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论