过去,当我处理长时间运行的 C++ 守护进程时,我不得不处理堆碎片问题。为了避免耗尽连续的堆空间,需要保留大量分配池等技巧。
这仍然是 64 位地址空间的问题吗?性能对我来说不是问题,所以我宁愿简化我的代码,不再处理缓冲池之类的事情。有没有人有关于这个问题的经验或故事?我使用的是 Linux,但我想许多相同的问题也适用于 Windows。
过去,当我处理长时间运行的 C++ 守护进程时,我不得不处理堆碎片问题。为了避免耗尽连续的堆空间,需要保留大量分配池等技巧。
这仍然是 64 位地址空间的问题吗?性能对我来说不是问题,所以我宁愿简化我的代码,不再处理缓冲池之类的事情。有没有人有关于这个问题的经验或故事?我使用的是 Linux,但我想许多相同的问题也适用于 Windows。
这仍然是 64 位地址空间的问题吗?
不,这仍然不是问题。
您是正确的,这是 32 位系统上的问题,但它不再是 64 位系统上的问题。
64 位系统上的虚拟地址空间非常大(在今天的 x86_64 处理器上目前为 2^48 字节,随着新的 x86_64 处理器的问世,虚拟地址空间将逐渐增加到 2^64),以至于连续的虚拟地址空间不足由于碎片化几乎是不可能的(除了一些高度人为的极端情况外)。
(这是一个常见的直觉错误,原因是 64 “只有”双 32,这导致人们认为 64 位地址空间大约是 32 位地址空间的两倍。事实上,一个完整的 64 位地址空间是 32 位地址空间的 40 亿倍。)
换句话说,如果您的 32 位守护程序需要一周时间才能分段到无法分配 x 字节块的阶段,那么至少需要一千年才能将今天的 x86_64 处理器的 48 位地址空间分段,并且将未来计划的完整 64 位地址空间分段需要8000 万年。
堆碎片在 64 位和 32 位下同样是一个问题。如果您发出大量具有不同生命周期的请求,那么您将获得一个碎片堆。不幸的是,64 位操作系统在这方面并没有真正的帮助,因为它们仍然不能真正洗牌周围的小块空闲内存以形成更大的连续块。
如果要处理堆碎片,仍然必须使用相同的旧技巧。
64 位操作系统在这里可以提供帮助的唯一方法是,如果有一些“足够大”的内存,您永远不会对其进行碎片化。
如果您的进程确实需要千兆字节的虚拟地址空间,那么升级到 64 位确实可以立即消除对变通办法的需要。
但值得计算出您希望进程使用多少内存。如果它只是在千兆字节或更少的区域内,那么即使是疯狂的碎片也不会让你用完 32 位地址空间 - 内存泄漏可能是问题所在。
(顺便说一句,Windows 的限制更大,因为它在每个进程中为操作系统保留了不礼貌的地址空间量)。