使用pugixml解释程序的内存消耗

时间:2013-07-31 06:55:41

标签: c++ profiling pugixml

我有一个解析大约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。

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

enter image description here

使用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时释放所有资源是的,但是在图表上看,我无法分辨这种情况(在时间轴上)。

1 个答案:

答案 0 :(得分:4)

您的假设不正确。

以下是如何估算pugixml内存消耗:

  1. 加载文档时,文档的整个文本将加载到内存中。所以你的文件是50 Mb。这是来自xml_document :: load_file - >的1个分配。 load_file_impl
  2. 除此之外,DOM结构包含到其他节点的链接等。节点的大小为32字节,属性的大小为20字节;这是针对32位进程的,对于64位进程乘以2。这来自xml_allocator的许多分配(每个分配大约是32kb)。
  3. 根据文档中节点/属性的密度,内存消耗的范围可以是,例如,文档大小的110%(即50 Mb - > 55 Mb)到600%(即50 Mb - > 300 Mb)。

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