内存泄漏如何提高性能

时间:2010-08-04 15:53:23

标签: c++ performance memory-leaks

我正在构建一个充满节点的大型RTree(空间索引)。它需要能够处理许多查询和更新。对象不断被创建和销毁。我正在运行的基本测试是随着树中对象数量的增加而看到树的性能。我插入100-20000一致大小,随机定位的对象,增量为100.搜索和更新与我目前面临的问题无关。

现在,当 NO 内存泄漏时,“插入树”性能无处不在。它从大约15000个物体到10.5秒到大约18000个物体。没有任何模式。

当我故意添加泄漏时,就像放入“new int”一样简单我没有把它分配给任何东西,即它本身就有一条线,性能立即落在一条漂亮的柔和曲线上,从100个物体的0(大约)秒倾斜到整个20k的1.5。

非常,此时非常失落。如果你想要源代码,我可以包含它,但它是huuugggeeee,字面意思是唯一有所作为的是“new int”。

提前致谢! -nick

5 个答案:

答案 0 :(得分:2)

我不确定你是怎么想出这个new int测试的,但这不是解决问题的好方法:)使用分析器运行代码并找出实际延迟的位置。然后集中精力固定热点。

g ++内置它 - 只需使用-pg

进行编译

答案 1 :(得分:2)

没有更多信息,我们无法确定。

但是我想知道这是否与堆碎片有关。通过创建释放许多内存块,您可能会创建一大堆连接在一起的小内存片段。内存管理器需要跟踪它们,以便在需要时再次分配它们。

当你释放一个块时,一些内存管理器试图将它与周围的内存块“合并”在一个高度分散的堆上,这可能会非常慢,因为它试图找到周围的块。不仅如此,如果您的物理内存有限,它可以“触摸”内存块的许多物理页面,因为它跟随内存块链,这可能导致整个负载极慢的页面错误,速度变化很大,具体取决于确切的操作系统决定给这个过程多少物理内存。

通过留下一些未释放的内存,您将改变这种访问模式,这可能会对速度产生很大影响。例如,您可能会强制运行时库每次分配新的内存块,而不是必须跟踪适当大小的现有块以进行重用。

我没有证据证明你的程序中存在这种情况,但我确实知道,当执行大量新的和免费的时,内存碎片通常是程序运行缓慢的原因。

答案 2 :(得分:0)

正在发生的事情可以解释这个(理论)

  1. 编译器未删除空的新int
  2. 新的int位于内部循环之一或递归遍历中的某个位置,其执行时间最长
  3. 流程的整体RSS增加,最终流程使用的总内存
  4. 由于此原因发生了页面错误
  5. 由于页面错误,进程变为I / O绑定而不是CPU绑定 最终结果,您会看到吞吐量下降。如果您能提及正在使用的编译器以及用于构建代码的编译器选项,将会有所帮助。

答案 3 :(得分:0)

我在黑暗中捅了一下,但问题可能就是堆碎片的方式。你说你正在创造一个破坏大量的物体。我将假设对象都是不同的大小。

当在堆上分配内存时,需要大小的单元从堆中断开。释放内存后,单元格将添加到空闲列表中。当一个人执行新的alloc时,分配器会遍历堆,直到找到足够大的单元。在进行大量分配时,空闲列表可能会变得相当长,并且遍历列表可能需要花费很多时间。

现在int很小。因此,当你执行新的int时,它可能会占用空闲列表中的所有小堆单元,从而大大加快了更大的分配。

然而,您可能正在分配和释放类似大小的对象。如果您使用自己的freelists,您将安全地进行许多堆散步,并可能显着提高性能。这正是STL分配器为提高性能所做的工作。

答案 4 :(得分:-1)

解决方案:不要从Visual Studio运行。实际上运行.exe文件。弄清楚这是因为这是剖析器正在做的事情,数字神奇地下降。检查内存使用情况和版本运行情况(并给我一些特别的时间)并没有达到过大的尺寸。

解决为什么地狱Visual Studio会像这样荒谬的废话:没有线索。