在C#中管理大型对象

4

我有一大批类似树形结构的对象。我遇到一个问题,应用程序使用的内存量开始接近1GB,这意味着机器性能下降,并且会出现内存不足的错误指令。

我通过使用SQLite将对象放入表中来解决此问题,从而有效地管理数据,但由于某些原因,这不再是一种可行的解决方案(我在这里不详细说明)。

您有什么建议来解决这种情况吗?我没有(真正的)数据库可供使用,所以我考虑的解决方案是模仿SQLite过程并使用一些文件后端存储——是否已经存在纯Dot Net或者这是一个复杂的DIY情况?

4个回答

7
当您开始存储大量对象时,对象分配开销会成为一个真正的问题。例如,在32位系统上运行.NET时,分配任何对象都需要至少16个字节。在64位系统上,每个对象最少需要24个字节。如果您的单个对象很小,则分配开销是一个巨大的代价。
您说过您有一个“树形结构”。如果没有更多关于您的应用程序的详细信息,我不能确定这是否适用,但大多数树形结构需要指向子节点的指针和(有时)指向父节点的指针。尽管树结构非常有用,但它们有时会产生非常大的开销。父节点和子节点链接通常需要使用树的总内存的50%或更多。
在C#中,您可以通过使用struct而不是对象来减轻分配开销,因为struct基本上没有分配开销。当然,缺点是您必须处理有时非常不方便的值类型语义。
还可以将许多树结构折叠成数组,消除子节点和父节点链接,从而节省大量内存。这通常会以更复杂的代码和一些运行时效率损失为代价。
在我的工作中,我经常不得不在内存中保留非常大的集合(数亿个节点)。当您在内存中拥有2.5亿条记录时,每个节点中的4个字节需要另外1GB的RAM。即使在16 GB的机器上,维护这样的数据结构也需要非常谨慎地考虑内存的使用方式。
如果必须将整个内容保留在内存中,则建议您尽可能将树节点设置为struct。您还应该考虑替代存储树的方法-消除与父节点或子节点的显式链接的方法。没有更多关于您特定应用程序的信息,我无法提出更具体的建议。

在我的工作流程中,我添加了一个新步骤来将数据持久化到动态定义的DataSet中,并强制进行垃圾回收 - 目前它运行良好。感谢您的提示和建议! - Simon P

4

1

一开始就有几个显而易见的问题: 1. 为什么需要一次性存储如此大的树结构? 2. 这些数据最初来自哪里?

无论您对这些问题有何答案,都有可能不需要一次性将所有数据存储在内存中。将更大量的数据持久化到磁盘上,并仅在需要时读取所需的位。看起来这正是您要走的方向。除了 RDMS 外,在 .NET 中有许多可能存储数据的地方;平面文件、xml 文件、隔离存储等。或者也许您可以让提供这些数据的系统(问题 #2)每次只提供较小的数据块? 如果您绝对需要将大型树结构存储在内存中,请研究一些树结构算法,或者甚至数据压缩?


数据来自于一个不可查询的数据源 - 它是整个源元素或者什么都没有。整个结构被保留,因为最终的显示取决于树中结果的数量。 - Simon P

0

我受到第三方(即我的公司 :) )对解决方案集的限制。 - Simon P

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接