如何用WinDbg计算内存转储中.NET 6缓存的ConcurrentDictionary保留大小?
获取.NET 6 ConcurrentDictionary缓存的精确内存占用方案
用WinDbg结合SOS扩展计算保留大小
完全可以用WinDbg获取ConcurrentDictionary的完整保留大小,步骤如下:
- 生成完整内存转储:
- 用任务管理器右键目标进程,选择“创建转储文件”;或者在WinDbg中附加进程后执行命令:
.dump /ma full_cache_dump.dmp/ma参数确保生成包含所有内存的完整转储。
- 用任务管理器右键目标进程,选择“创建转储文件”;或者在WinDbg中附加进程后执行命令:
- 加载SOS调试扩展:
执行命令加载.NET调试扩展(针对.NET Core/.NET 6,需匹配运行时版本):.loadby sos coreclr - 定位ConcurrentDictionary实例:
用!dumpheap命令筛选出目标字典类型的实例:
从输出中找到你要分析的字典实例的内存地址(比如!dumpheap -type System.Collections.Concurrent.ConcurrentDictionary0x0000021a3f45e0c0)。 - 计算保留大小:
用!objsize命令计算该实例及其所有依赖对象的总内存占用:
这个结果包含字典内部的数组、键值对结构、!objsize 0x0000021a3f45e0c0CacheItem值类型实例,以及CacheItem中引用的byte[]等所有关联数据。注意:如果缓存中的
byte[]等对象被其他代码引用,!objsize会重复计算这部分内存。若要得到字典独占的内存,需结合支配树分析。 - 细致拆分分析:
若要查看内部结构的大小分布,用!dumpobj命令查看字典的内部字段:
找到内部的!dumpobj 0x0000021a3f45e0c0m_tables等数组字段,再对这些数组地址执行!objsize或!dumpheap,逐个统计各部分的内存占用。
其他可用工具
dotMemory
JetBrains的dotMemory可以直观分析内存快照:
- 生成快照后,在对象列表中找到目标
ConcurrentDictionary实例,查看保留大小(Retained Size),该值就是字典及其所有独有依赖对象的总内存。 - 支持展开对象树,查看每个
CacheItem、内部数组、byte[]的具体大小,还能通过支配树排除共享引用的对象,结果精准。
Visual Studio内存诊断工具
- 在Visual Studio中启动调试,点击“调试”->“内存快照”生成快照。
- 在内存分析器的“对象”视图中找到
ConcurrentDictionary,查看其保留大小,还能对比多个快照分析内存变化趋势。
dotnet-dump命令行工具
适合无GUI的服务器环境:
- 用以下命令生成转储:
dotnet dump collect -p <进程ID> - 进入分析模式:
dotnet dump analyze <转储文件路径> - 同样使用SOS命令(如
!objsize、!dumpheap)计算保留大小,操作逻辑和WinDbg一致。
额外注意点
- 你的
CacheItem是值类型,它会直接存储在ConcurrentDictionary的内部数组中,而非作为独立引用对象,所以!objsize会包含这些值类型实例本身的大小(包括字段对齐、填充等内存开销)。 - 若要获取最精准的独占内存,优先使用工具的支配树功能,它会排除被其他对象共享引用的部分。
内容的提问来源于stack exchange,提问作者Denis
相关产品推荐
相关产品推荐

