Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 大对象堆友好IDictionary_C#_Large Object Heap - Fatal编程技术网

C# 大对象堆友好IDictionary

C# 大对象堆友好IDictionary,c#,large-object-heap,C#,Large Object Heap,我们有一个应用程序,它在多个字典中保存大量对象,其中一些对象在应用程序的生命周期内不断增长(使用大量工具和不断增长的订单/交易的交易应用程序) 由于大对象堆的碎片化,我们在OutOfMemoryExceptions方面遇到了问题 为了解决这个问题,我尝试编写一个“大”字典,它实现为两级字典,其中所有叶字典都不够大,无法在LOH上分配。我使用了一致的散列算法,以避免在单个存储桶变得太大时必须重新散列整个字典。一致散列“圈”是C5集合库中的一个TreeDictionary 我的问题是,对于C#,是否

我们有一个应用程序,它在多个
字典中保存大量对象,其中一些对象在应用程序的生命周期内不断增长(使用大量工具和不断增长的订单/交易的交易应用程序)

由于大对象堆的碎片化,我们在
OutOfMemoryException
s方面遇到了问题

为了解决这个问题,我尝试编写一个“大”字典,它实现为两级字典,其中所有叶字典都不够大,无法在LOH上分配。我使用了一致的散列算法,以避免在单个存储桶变得太大时必须重新散列整个字典。一致散列“圈”是C5集合库中的一个
TreeDictionary

我的问题是,对于C#,是否有更好的数据结构(或者可能是我描述的更好的实现)

更新

这是“大型”词典的实现:


我理解这不是万无一失的,因为规范中既没有LOH堆阈值,也没有每个字典条目或缩放算法的大小。然而,这是目前我能想到的避免应用程序在中午爆炸的最好方法。

我认为这需要改变算法

据我所知,GC非常擅长打包和整理内存碎片。因此,您的问题源于一个简单的事实,即您在内存中保存了太多的数据

您在内存中保存了多少数据

你想过使用数据库吗?紧凑型就足够了

或者简单地告诉你的客户,要正确运行你的应用程序,他需要16GB的内存。如果你的应用程序需要所有16 GB的内存,那么肯定是出了问题

编辑: 从不同的角度来看你的问题,在阅读了你的编辑后,我有了一个问题:你的物体有多大?或者它们是否包含长列表或数组?您多长时间删除/添加一次这些对象

我认为问题可能不在字典本身,而是对象太大,而且删除/添加太频繁。也许使用某种捕猎或游泳池可能是有利可图的。如果你使用列表,那么就创建那些预先定位的列表


也许使用可替换结构而不是可变类可以减轻碎片化的问题。

字典是应用程序中最大的数据结构,但它是一种不幸的数据结构。当哈希表变得太满时,它的大小通常是原来的两倍,在调整大小的过程中需要150%的超额分配,就在关键时刻。哈希表在庞大时工作得非常出色,但它需要连续分配,这会给堆算法带来压力

您可以使用多级哈希表来减少这些缺点,例如使用哈希代码的一个字节作为256个哈希表的索引。这无疑会增加一些开销,但更重要的是,这种策略和其他策略都充满了风险,因为它们会干扰随机性,比如您得到的哈希代码的随机性,并可能使性能变得非常糟糕。使用这种方法需要一个良好的理论基础和坚实的实证检验。但它可以工作


另一种策略是为最坏的情况预先分配最大的数据结构,并尽早分配。没有必要进行细粒度的分配,但现在如果它用完了,您将面临灾难性失败的幽灵。这是一个选项。

这可能有助于告诉你在现有的实现中看到了什么问题?如果你将字典用作扁平对象的键值存储,你可能会考虑一个内存映射文件。我们花了很多时间研究内存分析器(特别是redgate ANTS内存分析器)。我们已经将所有潜在的泄漏减少到实际使用的内存相对恒定的程度。剖析者指出,LOH特别零碎。目前,LOH运行3小时后,使用了10.37MB,但分配了435.4MB,最大的可用片段为49.83MB。在使用“大型”字典实现之前,情况更糟。为什么不使用本地数据库,如squlite或SQL compact edition?您将能够轻松地索引和查询您的需求,并且数据库将根据情况管理缓存。这就是创建数据库的全部原因,如果你的应用程序崩溃,那么你失去了一切,但数据库将维护一切。甚至像Auto Cad这样的应用程序也使用数据库来存储其复杂的3D结构。+1“你在内存中保存了多少数据?”与其调整你的字典,不如利用你最近获得的经验重新评估你的需求。长期目标是减少我们在内存中的交易/订单数量,但这在短期内是不可行的。不幸的是,两者都没有用64位操作系统取代trader的所有32位XP机器。@Akash,这不是一个很好的解决方案,只是将内存需求推到了另一个进程上。我想要的是数据库中可能使用的任何智能数据结构,以避免这种情况。话虽如此,我怀疑CLR上是否有专门针对此问题编写的RDBMS…-1缺少OP问题中的一个关键点,并且包含关于GC和碎片整理的基本错误信息。正如OP提到的,“大对象堆的碎片化”。在.NET4.5.1之前,没有办法重新定位大型对象,而且字典是创建大型对象的最糟糕的违规者之一,因为它在增长,除非事先知道最大大小。问题确实在字典里。在过去的几年中,我已经多次遇到这个问题(尽管直到今天,我始终能够在不切换到IDictio的自定义实现的情况下解决它)