You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 16:05:12