我们偶尔会接到的问题,从而我们的长期运行服务器的进程(上运行的Windows服务器2003年)已经抛出的一个例外,由于存分配失败。我们怀疑的是,这些拨款是失败的,由于记忆碎片。

因此,我们已经看过一些替代的记忆分配机制,可以帮助我们和我希望有人能告诉我最好的之一:

1)使用Windows 低碎片堆

2)jemalloc-作为使用 Firefox3

3)Doug Lea malloc

我们的服务器进程的是开发利用跨平台C++编码,因此,任何解决方案将是最理想的交叉平台还(执*尼克斯的操作系统遭受这种类型的存碎片?).

此外,我认为LFH现在是默认存分配机制,Windows服务器2008/Vista?...我当前的问题"走开"如果我们的客户只需提升他们的服务器操作系统?

有帮助吗?

解决方案

首先,我同意与其他的海报的建议的资源泄漏。你真的想要规则,即第一次。

我们希望,堆的经理,你目前正在使用的一种方式倾倒出实际的总额可用空间堆(在所有 免费的 块)和也的区块总数,它被划分了。如果平均免费块的大小是相对小的比总的自由空间堆,那么你有一个分裂的问题。或者,如果你可以转储的大小,最大的免费块和进行比较,总的免费空间,这将完成同样的事情。最大的免费块将是小相对于总 免费的 空间可以在所有块如果运行成碎片。

是非常清楚的关于上述,在所有情况下,我们正在谈论 免费的 块堆中,不能分配的区块堆。在任何情况下,如果上述条件得不到满足,然后你 有一个泄漏的情况的某种。

因此,一旦排除了有泄漏,可以考虑采用更好的分配器。 道格Lea的malloc 建议在该问题是一个非常好的分配使用的应用程序和非常健壮 大多数 的时间。把另一个方式,已经经过时间考验的工作非常好,对于大多数的任何应用程序。然而,没有算法的理想 所有 应用程序和任何管理算法的方法可以通过正确的pathelogical条件对它的设计。

为什么你有一个分裂的问题? -来源碎片问题 引起 由的行为的应用程序和必须做大大不同的分配寿命在同一个存储场。这是,某些对象是分配和释放的定期同时其他类型的对象持续存在延长的时期都在同一堆。....觉得较长的使用寿命的戳孔进入更大的区域的竞技场,从而防止合并的相邻区块,已经释放。

为解决这类问题,最好的事情可以做的是在逻辑上分堆成分领域的寿命更多的相似。在效果,你想要一个瞬时堆和持久堆堆或该组的事情相似的寿命。

其他一些人建议另一种方法要解决的问题,这是企图使分配大小更多的类似或相同,但是这是不太理想,因为它创造了一种不同类型的碎片称为内部碎片-这是在浪费空间,你有通过分配更多的内存在的框比你所需要的。

此外,有一个良好的堆分配,就像Doug Lea,使块的大小,更多的类似的是不必要的,因为分配程序,将已经这样做的一个电的两个大小的方案存入桶,这将使它完全不需要人工调整分配大小通过malloc()-在作用,他堆的经理,你自动更加强劲于应用程序将能够进行调整。

其他提示

我认为你已经错误地排除了一个存储器泄漏太早。即使是一个微小的记忆泄漏可能会导致严重的记忆碎片。

假设你的应用程序的行为如下:
分配10M
分配1byte
免费10M
(哎呀,我们没有免费的1个字节,但谁在乎1小小的字节)

这似乎是一个非常小的泄漏, 你几乎不会注意到它在监视刚才的总分配的存储器的尺寸.但是这种泄漏的最终会导致应用程序记忆看起来是这样的:
.
.
免费的–10M
.
.
[分配-1字节]
.
.
免费的–10M
.
.
[分配-1字节]
.
.
免费的–10M
.
.

这个漏洞将不会发现...直到你想要分配11MB
假设你有充分的小型转储存的信息包括在内,我建议使用 DebugDiag 来点可能的泄漏。在所生成的记忆的报告, 仔细地审查分配计数(不大小).

作为你的建议,Doug Lea的malloc可能的工作。它的跨平台,它已使用的运输代码。至少,它应当易于纳入你的代码进行测试。

曾在固定的存储环境,多年来,这种情况当然是一个问题,即使在非固定的环境。我们已经发现,CRT分配倾向于臭漂亮的不好的方面的业绩(速度、效率浪费空间,等等)。我坚定地相信,如果你有广泛需要的一个良好的记忆分配程序在很长一段时间,你应该编写自己的(或者看看是否喜欢的东西dlmalloc会的工作)。诀窍是得到书面的东西与你分配模式,以及有更多的与存管理效率,因为几乎其他任何东西。

给dlmalloc一个尝试。我肯定给它一个大拇指。这是相当可调谐,所以你可能能够获得更高的效率,通过改变某些编纂的时间选择。

老实说,你不应该取决于事"走开"用新的操作系统的实现。服务包装、贴,或者另一个新的操作系统N年后可能会使问题变得更糟。再次,对于应用需要一个强大的存管理器,不使用库存的版本,都可以与你的编译器。找到一个适合 你的 情况。开始与dlmalloc和调整它来看看你是否可以得到的行为最适合于你的情况。

你可以帮助减少碎片通过减少分配释放.

例如说对一个网络服务器运行,服务器侧脚本,它可以创建一串出该网页。而不是分配和释放这些字符串的每一页的请求,就保持一个游泳池他们,所以你唯一的分配当你需要更多的,但是你不释放(这意味着一段时间后你得到你的情况没有分配了,因为你有足够的)

你可以使用_CrtDumpMemoryLeaks();要转储存泄漏向调试窗口在运行调试的建立,然而我相信这是特有的视觉C编译器。(这是在crtdbg.h)

我怀疑泄漏之前怀疑碎片。

对于存储器密集的数据结构,可以切换至重复使用的储存池的机制。你可能还能够分配更多的东西堆而不是堆,但在实际条款,不会使一个巨大的差异,我想。

我火了类似的工具才或者做一些密集型的采伐寻找资源不被释放。

@nsaners-我非常确定的问题是存碎片。我们已经分析 小型转储 这一点的一个问题当大(5-10m)块的记忆正在进行分配。我们还监控的程序(在现场和在发展)检查存储器泄漏-没有检测到(内存占用一般很低)。

该问题不会发生在Unix,虽然这通常不是作为糟糕。

低framgmentation堆帮助我们,但我的同事发誓 聪明堆 (它已经使用交叉平台,在几个我们的产品年)。不幸的是,由于其他情况下,我们不能使用智能堆的这段时间。

我们还看方框/分块分配和试图拥有范围精明的游泳池/战略,即, 长期的东西在这里,整个要求的事,短期的东西在那边,等等。

像往常一样,你可以从废物存储器获得的一些速度。

这种技术不是用于一般目的分配程序,但它确实有它的位置。

基本上,想法是编写一个分配器,返回忆从一个游泳池在哪里的所有拨款都是同样大小。这个游泳池永远不能成为碎片,因为任何一块是不如另一个。你可以减少存储器的浪费,通过创建多个游泳池有不同大小的块和挑选最小的区块大小的游泳池,仍然大于所要求的数额。我用这个想法建立分配中运行的O(1)。

该简单、快速的和肮脏的,解决方案是分裂的应用到 几个过程, ,你应该得到新鲜堆每次创建的进程。

你的记忆和速度可能会遭受一点(交换),但快速的硬件和大RAM应该能够帮助。

这是老UNIX招守护进程,当线不存在。

如果你在谈论Win32-你可以尝试挤压的东西通过使用LARGEADDRESSAWARE.你会有-1gb额外的碎片的记忆,所以您应用程序将片段更长的时间。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top