gpt4 book ai didi

c# - 从静态对象中包含的 C# 字典中释放内存

转载 作者:可可西里 更新时间:2023-11-01 07:45:39 25 4
gpt4 key购买 nike

我在使用 WCF Web 服务时遇到了一些问题(一些转储、内存泄漏等),并且我运行了一个 profillng 工具(ANTS 内存配置文件)。

只是为了发现即使处理结束(我运行特定测试然后停止),第 2 代也有 25% 的内存用于 Web 服务。我追踪这段内存,发现我有一个充满 (null, null) 项目的字典对象,哈希码为 -1。

Web 服务的工作流意味着在特定的处理过程中,项目被添加然后从字典中删除(只是简单的 AddRemove )。没什么大不了的。但似乎在删除所有项目后,字典中充满了 (null, null) KeyValuePair秒。实际上有数千个,以至于它们占据了很大一部分内存并最终发生溢出,相应的强制应用程序池回收和 DW20.exe 获得了它可以获得的所有 CPU 周期。

字典其实是Dictionary<SomeKeyType, IEnumerable<KeyValuePair<SomeOtherKeyType, SomeCustomType>>> ( System.OutOfMemoryException because of Large Dictionary ) 所以我已经检查过是否有某种引用资料。

字典包含在一个静态对象中(通过处理使不同的处理线程可以访问它)所以从这个问题和更多(Do static members ever get garbage collected?)我理解为什么那个字典在第 2 代中。但这也是那些(null,null)的原因?即使我从字典中删除项目,内存中也会始终占用某些内容吗?

这不是这个问题中的速度问题 Deallocate memory from large data structures in C# .似乎内存永远不会被回收。

我能做些什么来真正从字典中删除项目,而不仅仅是继续用 (null, null) 对填充它吗?还有什么我需要检查的吗?

最佳答案

字典将项目存储在哈希表中。为此内部使用了一个数组。由于哈希表的工作方式,该数组必须始终大于实际存储的项目数(至少大 30%)。 Microsoft 使用 72% 的负载因子,即至少有 28% 的数组为空(参见 An Extensive Examination of Data Structures Using C# 2.0,尤其是 The System.Collections.Hashtable ClassThe System.Collections.Generic.Dictionary Class ) 因此 null/null 条目可以代表这个空闲空间。

如果数组太小,会自动增长;然而,当项目被删除时,数组不会收缩,但将释放的空间应该在插入新项目时重新使用。

如果你控制了这个字典,你可以尝试重新创建它以缩小它:

theDict = new Dictionary<TKey, IEnumerable<KeyValuePair<TKey2, TVal>>>(theDict);

但问题可能来自实际(非空)条目。你的字典是静态的,因此永远不会被垃圾收集器自动回收,除非你给它分配另一个字典或 null (theDict = new ...theDict = 空)。这仅适用于静态字典本身,而不适用于其条目。只要对已删除条目的引用存在于其他地方,它们就会持续存在。 GC 将回收任何无法通过某些引用访问的对象(较早或较晚)。无论此对象是否声明为静态,都没有区别。对象本身不是静态的,只有它们的引用。


正如@RobertTausig 友善地指出的那样,自 .NET Core 2.1 以来 有新的 Dictionary.TrimExcess(),这是您真正想要的,但没有存在于当时。

关于c# - 从静态对象中包含的 C# 字典中释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15022528/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com