STL可以帮助解决内存碎片问题

时间:2014-06-23 13:40:41

标签: c++ windows memory stl

这是关于正在开发的新TCP服务器(在Windows / VC2010上的C ++中)

成千上万的客户端连接并继续发送大量异步请求。我将传入的请求存储在原始链表(结构的'C'样式链表,每个结构是一个请求)中,并在同步线程中逐个处理它们。

我在newdelete中使用来创建/销毁这些请求结构。

到目前为止,我认为这是最有效的方法。但最近我发现,即使所有客户端断开连接,服务器进程的私有字节仍显示大量内存消耗(大约45 MB)它从未恢复到原来的水平。

我经常挖掘并确保没有内存泄漏。最后,我遇到了this并意识到了它,因为很多newdelete次调用导致了内存碎片。

现在我的几个问题是:

  1. 如果我用STL数据结构替换我的原始链表来存储传入的请求,它会帮我摆脱内存碎片吗? (因为根据我的知识,STL使用连续的块。它自己的内存管理类型导致碎片非常少。但我不确定这是否属实。)

  2. 与原始链接列表相比,该情况会对性能产生什么影响?

4 个答案:

答案 0 :(得分:2)

我怀疑您的主要问题是您使用的是链接列表。链接列表对于这种事情是可怕的,并且导致您看到的问题。很多年前,我编写的TCP代码做了非常类似的事情,用普通的C语言。处理这个问题的方法是使用动态数组。最终你的分配要少得多。

在那些糟糕的旧时代,我自己动手,实际上非常简单。只需为一些记录分配单个数据结构,比如十个。当您要溢出时,将尺寸加倍,重新分配和复制。因为您以指数方式增加大小,所以您将永远不会拥有多个分配,从而使碎片成为无问题。此外,您没有列表附带的开销。

实际上,几乎不应该使用列表。

现在就你的实际问题而言,是的,STL应该帮助你,但不要使用std:list。以我刚才概述的方式使用std:vector。根据我的经验,在95%的案例中,std:list是次要的选择。

如果您使用std:vector,则可能需要使用vector::reserve来预分配您希望看到的记录数。它会为你节省一些分配。

答案 1 :(得分:1)

您是否看到内存使用和碎片导致性能问题?我认为这更多来自于new / delete。除非您使用自己的分配器并预先分配大块并自行管理,否则STL可能无济于事。换句话说,它需要做很多工作。

如果你拥有它,通常可以使用内存。您可能需要考虑汇集您的请求结构,这样您就不需要重新分配它们。然后,您可以按需分配并将其添加到池中。

答案 2 :(得分:0)

  1. 也许。 std::list动态分配每个节点,就像自制链接列表一样。 " STL使用连续的块..." - 这不是真的。您可以尝试std :: vector,它就像一个数组,因此会导致更少的内存碎片。取决于您需要的数据结构。

  2. 我不希望(良好实施的)自制链接列表和std :: list之间在性能上有任何明显的差异。如果你需要一个堆栈,std::vector效率更高,如果你需要一个队列(例如fifo),那么std::deque比链接列表更有效。

  3. 如果您认真考虑防止内存碎片,则需要管理自己的内存和自定义分配器或使用某些第三方库。这不是一项微不足道的任务。

答案 3 :(得分:0)

您可以使用std :: unique_ptr代替原始指针。它具有最小的开销,并确保您的指针被删除。

在我看来,很少有情况下链表是数据结构的正确选择。您需要根据数据使用方式选择数据结构。例如,使用向量将数据保持在一起,这对于缓存很有用,如果您可以设法添加/删除元素,那么就可以避免碎片。

如果您想避免新/删除的开销,可以汇集对象。这样你仍然需要处理碎片。