加载大量XML文件时的内存管理

时间:2009-03-24 10:22:54

标签: c++ xml memory memory-management

我们有一个从XML导入对象的应用程序。 XML大约为15 GB。应用程序总是开始耗尽内存。我们试图在操作之间释放内存,但这会导致性能下降。即完成导入操作需要更多时间。 CPU利用率达到100%

该应用程序是用C ++编写的。

频繁拨打free()是否会导致性能问题?


来自OP的评论:在expat中使用的解析器,这是一个占用空间非常小的SAX解析器,以及可自定义的内存管理。

9 个答案:

答案 0 :(得分:5)

使用SAX解析器而不是DOM解析器。

答案 1 :(得分:3)

您是否尝试过恢复内存和类,而不是释放和重新分配它?常量分配/释放周期,特别是如果它们与小的(少于4096字节)数据片段耦合,可能会导致严重的性能问题和内存地址空间碎片。

答案 2 :(得分:2)

在其中一个令人烦恼的负载中描述应用程序,以查看它在大部分时间内花费的时间。

我认为free()有时可能代价高昂,但这当然在很大程度上取决于平台的实施。

另外,你没有说明加载对象的生命周期;如果XML是15 GB,那么一旦解析并丢弃标记,每个“对象”会保留多少?

以流式方式处理此大小的输入文档听起来很明智,即不尝试一次加载和构建整个XML解析树的DOM方法。

答案 3 :(得分:1)

如果您想最大限度地减少内存使用量,请查看How to read the XML data from a file by using Visual C++

答案 4 :(得分:1)

通常有用的一件事是使用轻量级的低开销内存池。如果你把它与“框架”分配方法结合起来(忽略任何删除/免费,直到你完成所有数据),你可以得到一些非常快的东西。

我们最近为嵌入式系统做了这个,主要是出于性能原因,但它也节省了大量内存。

诀窍基本上是分配一个大块 - 比我们需要的稍大一些(如果你愿意,你可以分配一个块链) - 并且只是继续返回一个“当前”指针(通过allocSize来增加它) ,在我们的情况下,每次舍入到最大对齐要求4)。这将每个alloc的开销从52-60字节减少到< = 3字节。我们也忽略了“免费”调用,直到我们都完成解析然后释放整个块。

如果你的框架分配足够聪明,你可以节省大量的空间和时间。它可能无法让你一直到15GiB,但是值得看看你真正拥有多少空间开销......我对基于DOM的系统的经验是他们使用了大量的小型分配,每个分配都相对较高开销。

(如果您有虚拟内存,如果您在任何给定时间的访问权限在一个或三个页面的本地,那么一个大的“块”可能甚至不会造成太大的伤害......)

显然,从长远来看,你必须保留你实际需要的内存,但解析器的“临时内存”会以这种方式变得更加高效。

答案 5 :(得分:0)

  

我们试图在操作之间释放内存,但这会导致性能下降。

     

频繁调用free()会导致性能问题吗?

根据提供的证据,是的。

既然你已经使用了expat,一个SAX解析器,你究竟是什么free?如果你可以释放它,为什么你首先将它malloc放在一个循环中?

答案 6 :(得分:0)

也许,它应该说是探查者。

另外不要忘记使用堆的工作是单线程的。我的意思是如果您的线程的展位将在ont时间分配/释放内存,其中一个将在第一次完成时等待。

如果为相同的对象分配和释放内存,则可以创建此对象的池并进行一次分配/释放。

答案 7 :(得分:0)

尝试找到一种方法来分析您的代码。

如果您没有探查器,请尝试组织您的工作,以便您只有一些free()命令(而不是您建议的那些命令)。

在内存消耗和时间效率之间找到适当的平衡是很常见的。

答案 8 :(得分:0)

我自己没有尝试过,但是你听说过XMLLite,有MSDN artical介绍它。它由MS Office内部使用。