内存分配中的锁争用——多线程与多进程



我们开发了一个大型c++应用程序,它在大型Linux和Solaris机器(多达160个CPU内核甚至更多)上的几个站点上运行得令人满意。它是一个多线程(1000多个线程)、单进程架构,消耗大量内存(200 GB以上)。我们正在LD_PRELOADing Google Perftool的tcmalloc(或Solaris上的libumem/mtmalloc),以避免内存分配性能瓶颈,通常效果很好。然而,在一些较大的安装上,我们开始看到在内存分配/释放期间锁争用的不利影响,特别是在进程运行了一段时间之后(这暗示了分配器的老化/碎片效应)。

我们正在考虑更改为多进程/共享内存架构(繁重的分配/释放不会发生在共享内存中,而是发生在常规堆上)。

所以,最后,这是我们的问题:我们是否可以假设现代Linux内核的虚拟内存管理器能够有效地将内存分配给数百个并发进程?或者我们是否必须期望遇到与我们在单进程/多线程环境中看到的内存分配争用相同的问题?我倾向于希望有更好的整体系统性能,因为我们将不再局限于单个地址空间,并且拥有几个独立的地址空间将需要更少的虚拟内存管理器锁定。有人有任何实际经验或性能数据比较多线程和多进程内存分配吗?

我倾向于希望有一个更好的整体系统性能,因为我们将不再局限于单个地址空间,并且拥有几个独立的地址空间将需要更少的虚拟内存管理器锁定。

没有理由期待这一点。除非您的代码设计得非常糟糕,以至于它经常返回到操作系统来分配内存,否则它不会产生任何显著的差异。只有当应用程序需要更多虚拟内存时,才需要返回操作系统的虚拟内存管理器,一旦进程达到稳定的大小,这种情况就不会发生。

如果你一直在分配和释放返回到操作系统的空间,你应该停止这样做。如果您不这样做,那么您可以保留多个已经分配的内存池,这些内存池可以由多个线程使用而不会产生争用。而且,作为一个好处,您的上下文切换将更便宜,因为TLB不需要刷新。

只有当你不能减少地址空间更改的频率(例如,如果你必须映射和取消映射文件),或者如果你必须改变其他共享资源(如文件描述符),你应该考虑多进程选项

最新更新