我有一个应用程序,它读取3-4 GB的数据,从每一行中构建实体,然后将它们存储在列表中。
我遇到的问题是,内存变得疯狂,变得像13到15 GB。为什么存储这些实体需要这么多内存。
所以我构建了一棵树,并做了一些类似于Huffman编码的事情,总内存大小约为200 -300MB。
我明白,我压缩了数据。但我没想到在列表中存储对象会增加这么多内存。为什么会发生这种情况?
其他数据结构,如字典、堆栈、队列、数组等呢?
在哪里可以找到关于数据结构的内部结构和内存分配的更多信息?
还是我做错了什么?
发布于 2011-03-25 14:09:15
无论您将使用哪种数据结构,您的内存消耗永远不会低于存储所有数据所需的内存。
你计算过存储一个实例类对象需要多少内存吗?
您的huffman编码是一种节省空间的优化,这意味着您可以自己消除类对象中的大量重复数据。这与您用来保存数据的数据结构无关。这取决于数据本身的结构,以便您可以利用不同的节省空间的策略(其中huffman编码是众多可能性中的一种,适用于消除常见前缀,用于存储数据的数据结构是树)。
现在,回到你的问题上。在不优化数据(即对象)的情况下,您可以注意一些事情来提高内存使用效率。
我们所有的物体都有相似的大小吗?
你是不是只是运行一个循环,动态分配内存,然后把它们插入到一个列表中,就像这样:
foreach (var obj in collection) { myList.Add(new myObject(obj)); }在这种情况下,您的list对象将不断扩展。如果末尾没有足够的空闲内存来扩展列表,.NET将分配一个新的、更大的内存块,并将原始数组复制到新内存中。从本质上讲,您最终得到了两块内存--原始内存和新的扩展内存(现在保存列表)。多次执行此操作(显然您需要对GB的数据执行此操作),您将看到大量的碎片内存空间( of )。
只需一次性为整个列表分配足够的内存,这样会更好。
作为后记,我不禁想知道:你到底要如何搜索这个庞大的列表来找到你需要的东西?你不应该使用像二叉树或哈希表这样的东西来帮助你的搜索吗?也许你只是在读入所有的数据,对所有的数据进行一些处理,然后将它们写回……
发布于 2011-03-25 14:25:19
在.NET中,大对象位于未压缩的大对象堆中。Large是超过85,000字节的所有内容。当你增加你的列表时,它们可能会变得更大,一旦你超过了当前的容量,就必须重新分配。重新分配意味着它们很可能被放在堆的末尾。所以你最终得到了一个非常零碎的LOH和大量的内存使用。
更新:如果您使用所需的容量(我想您可以从数据库中确定)来初始化列表,那么您的内存消耗应该会降低一点。
发布于 2011-03-25 14:16:27
如果您使用的是类,请阅读下面的响应:Understanding CLR object size between 32 bit vs 64 bit
64位(您使用的是64位,对吗?)对象开销是16字节加上对对象的引用(有人在引用他,对吗?)所以又是8个字节。因此,一个空对象将“吃掉”至少24个字节。
如果您使用的是Lists,请记住Lists是通过加倍的方式增长的,因此您可能会浪费很多空间。其他.NET集合也以同样的方式增长。
我要补充的是,数以百万计的List的“纯粹”开销可能会让他的记忆崩溃。除了List对象“吃掉”的16 +8字节的空间之外,它(在.NET实现中)由2个it (8字节)、一个SyncLock引用(8字节,通常为空)和一个对内部数组的引用(所以8+ 16字节+数组)组成。
https://stackoverflow.com/questions/5429039
复制相似问题