C# HashSet容量充足时每次Add仍分配内存的技术问询
HashSet.Add 内存分配超出预期的问题排查
我通过BenchmarkDotNet编写基准测试,验证HashSet<Point>.Add方法的内存分配情况,结果超出预期:明明HashSet的容量足够容纳单个元素,在执行Clear()后调用Add()添加单个结构体元素,却每次都会产生24字节的内存分配,总分配量为迭代次数×24字节。
测试代码
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Running; using System.Collections.Generic; public struct Point { public int X, Y; } [MemoryDiagnoser] public class Program { public static void Main(string[] args) { BenchmarkRunner.Run<Program>(); } [Params(10, 500, 1000)] public int ArrayLength { get; set; } [GlobalSetup] public void Setup() { hs = new HashSet<Point>(100); // 初始化容量为100,确保有足够空间容纳单个元素 p = new Point(); // 在Setup中初始化结构体实例 hs.Add(p); // 预热执行,确保HashSet中已有至少一个元素 } Point p; HashSet<Point> hs; [Benchmark] public void Struct() { for (var i = 0; i < ArrayLength; i++) { // 多次重复执行测试操作 hs.Clear(); // 清空HashSet,使其元素数为0 hs.Add(p); // 重新添加单个元素 } } }
补充验证细节
为定位问题,我做了以下验证:
- 仅执行
hs.Clear()时,无任何内存分配 - 修改
Point结构体的字段数量后,单次Add()的分配字节数会随之改变 - 单独测试结构体复制操作,确认该过程无内存分配,排除结构体复制导致分配的可能,验证代码如下:
private Point t; public void Test(Point p){ t = p; } [Benchmark] public void Struct() { var test = new Point(1, 2); Test(test); }
该测试结果显示无内存分配,说明结构体复制不是导致问题的原因。
内容的提问来源于stack exchange,提问作者ApmeM
相关产品推荐
相关产品推荐

