大对象堆友好字典
本文关键字:字典 对象 | 更新日期: 2023-09-27 17:55:02
我们有一个应用程序,在几个Dictionary
中保存大量对象,其中一些对象在应用程序的生命周期中不断增长(交易应用程序具有大量工具和不断增长的订单/交易)。
由于大型对象堆的碎片,我们在OutOfMemoryException
s中遇到了问题。
为了解决这个问题,我试图写一个"大"字典,它被实现为一个两级字典,其中所有的叶子字典都不够大,无法在LOH上分配。我使用了一致哈希算法,以避免在单个桶变得太大时必须重新哈希整个字典。一致性哈希'circle'是来自C5 collections库的TreeDictionary
。
我的问题是,c#是否有更好的数据结构(或者可能是我描述的更好的实现)?
这是'大'字典的实现:https://gist.github.com/956621
我知道这不是万无一失的,因为规范中既没有LOH堆阈值,也没有每个Dictionary条目的大小或缩放算法。但是,这是目前我能想到的避免应用程序在中午崩溃的最好方法。
当字典是应用程序中最大的数据结构时,它是一个不幸的数据结构。当哈希表变得太满时,它的大小通常会增加一倍,并且在调整大小期间需要150%的超额分配,就在关键时刻。当哈希表非常大的时候,它可以很好地工作,但它需要连续分配,这强调了堆算法。
您可以使用多级哈希表来减少这些缺点,例如使用哈希码的一个字节作为256个哈希表的索引。这当然会增加一些开销,但更重要的是,这种策略和其他策略都充满了危险,因为它们会摆弄得到的哈希码的随机性,可能会使性能变得非常非常差。使用这种方法需要良好的理论基础和扎实的实证检验。但它可以工作。
另一种策略是为最坏的情况预先分配最大的数据结构,并尽早分配。没有必要进行细粒度的分配,但现在如果它耗尽,您将面临灾难性失败的幽灵。这是一个选项
我认为这需要改变算法。
根据我所听到和理解的,GC非常擅长打包和整理内存。所以你的问题源于一个简单的事实,你在内存中存储了太多的数据。
内存中有多少数据?
你考虑过使用数据库吗?紧凑的一个可能就足够了。
或者简单地告诉你的客户端,要正确运行你的应用程序,他需要16 GB的内存。如果你的应用需要所有的16gb内存,那么肯定有问题。
编辑:从不同的角度看你的问题,读了你的编辑后,我有一个问题:你的对象有多大?或者它们是否包含长列表或数组?你多久删除/添加一次这些对象?
我认为问题可能不在于字典本身,而在于对象太大,而且删除/添加得太频繁。也许用一些捕捉或水池可能是有利可图的。如果您使用列表,那么创建这些列表时使用预分配的。
也许使用不可变结构代替可变类可以缓解碎片化。