1

我有一个程序可以解析约 50MB 的 XML 文件并将数据提取到内部对象结构中,而没有指向原始 XML 文件的链接。当我试图粗略估计我需要多少内存时,我估计是 40MB。

但我的程序需要 350MB 之类的空间,我试图找出发生了什么。我使用boost::shared_ptr,所以我不处理原始指针,希望我没有产生内存泄漏。

我试着写我所做的,我希望有人能指出我的过程中的问题,错误的假设等等。

首先,我是如何测量的?我曾经htop发现我的内存已满,使用我的代码的进程正在使用大部分内存。为了总结不同线程的内存并获得更漂亮的输出,我使用了http://www.pixelbeat.org/scripts/ps_mem.py这证实了我的观察。

我粗略地估计了理论消耗量,以了解哪个因素介于消耗量和至少应该是什么之间。是10。所以我用来valgrind --tool=massif分析内存消耗。它表明,在 350MB 的峰值时,250MB 被xml_allocator来自pugixml库的称为的东西使用。我去了我的代码部分,我在其中实例化pugi::xml_document并放入std::cout对象的析构函数以确认它已被释放,这发生在我的程序的早期(最后我睡了 20 秒,以便有足够的时间来测量内存消耗,即使在析构函数的控制台输出出现后仍保持 350MB)。

现在我不知道如何解释这一点,并希望有人能在我做出错误假设或类似假设的地方帮助我。

在此处输入图像描述

最外面的代码片段使用pugixml类似于:

void parse( std::string filename, my_data_structure& struc )
{
    pugi::xml_document doc;
    pugi::xml_parse_result result = doc.load_file(filename.c_str());

    for (pugi::xml_node node = doc.child("foo").child("bar"); node; node = node.next_sibling("bar"))
    {
        struc.hams.push_back( node.attribute("ham").value() );
    }
}

而且由于在我的代码中我没有在pugixml某处存储元素(只有从中提取的实际值),所以我doc希望在离开函数时释放所有资源parse,但是在图表上看,我不知道在哪里(在时间轴上) 有时候是这样的。

4

1 回答 1

4

你的假设是不正确的。

以下是估算 pugixml 内存消耗的方法:

  1. 加载文档时,文档的整个文本都会加载到内存中。所以你的文件有 50 Mb。这是来自 xml_document::load_file -> load_file_impl 的 1 个分配
  2. 除此之外,还有包含指向其他节点的链接的 DOM 结构等。节点大小为 32 字节,属性大小为 20 字节;这是 32 位进程,乘以 2 是 64 位进程。这来自 xml_allocator 的许多分配(每个分配大约为 32kb)。

根据文档中节点/属性的密度,内存消耗的范围可以从文档大小的 110%(即 50 Mb -> 55 Mb)到 600%(即 50 Mb -> 300 Mb) .

当您销毁 pugixml 文档(调用 xml_document dtor)时,数据被释放 - 但是,根据操作系统堆的行为方式,您可能不会立即看到它返回到系统 - 它可能会留在进程堆中。要验证您是否可以尝试再次解析并检查第二次解析后峰值内存是否相同。

于 2013-07-31T17:06:54.587 回答