我在各种操作系统中遇到内存管理问题。
我的程序是一个服务器,可以执行一些可能需要几GB内存的处理。之后,它会在等待几个小时直到另一个请求到达时释放大部分内存。
在AIX和Solaris上,我观察到以下行为,
当我释放内存时,内存不会返回给操作系统。进程使用的虚拟内存量总是增加 - 永不减少。对于物理内存也是如此,直到它的极限。因此,似乎我们也在睡眠模式下使用所有这些内存。
何时可以将此内存返回给操作系统?我该怎么做?
Linux是不同的:它似乎有时会返回内存,但我无法理解何时以及如何。例如,我有一个场景,其中请求之前的过程是100MB,然后是高峰时的700MB,并且在释放所有下降到600MB之后。我不明白 - 如果Linux为操作系统提供内存,为什么不是全部?
答案 0 :(得分:8)
glibc库(通常用作Linux中的标准C库)可以通过两种方式分配内存 - 使用sbrk()或使用mmap()。它将使用mmap()进行足够大的分配。
使用sbrk()分配的内存不能轻易再次放弃(仅在特殊情况下,据我所知glibc甚至不尝试)。可以使用munmap()返回使用mmap()分配的内存。
如果您依赖于能够将内存返回到操作系统,则可以直接使用mmap()而不是malloc();但如果分配大量小块,这将变得效率低下。您可能需要在mmap()之上实现自己的池分配器。
答案 1 :(得分:4)
大多数情况下,在进程终止之前,内存不会返回到系统。根据操作系统和运行时库,可能会将内存返回给系统,但我不知道有任何可靠的方法来确保这种情况发生。
如果处理需要几GB内存,请让服务器等待请求,然后生成一个新进程来处理数据 - 您可以使用管道与服务器通信。处理完成后,返回结果并终止生成的进程。
答案 2 :(得分:2)
我假设,在libc中分配内存的方式(也许可以返回给OS)。您正在使用的编程语言/库堆栈可能是有原因的。
我认为glibc会在堆顶部返回非碎片内存。您的进程可能会分配它将始终使用的10MB数据。之后,将分配500MB用于处理的数据。 之后,分配一个甚至在处理之后保留的微小数据片段(可能是处理的结果)。之后再分配500MB 内存布局是:
|使用10MB | 500 MB处理| 1MB结果| 500MB处理| = 1011 MB总计
当释放1000MB时,内存布局为
| 10MB使用| 500MB释放| 1MB结果| 500 MB释放| glibc现在可能会在最后返回内存...... |使用10MB | 500MB释放| 1MB结果| = 511 MB“正在使用中” 也只使用了11MB。
我认为发生了什么,你需要做进一步的研究(单独的内存池),以确保释放所有内存
答案 3 :(得分:0)
我认为唯一的可靠的和便携式方法是生成一个新的进程以处理您的请求。在进程退出时,操作系统将收集所有相关的内存。
不幸的是,您产生与生成此流程和进程间通信相关的低效率(我注意到您正在进行大量处理 - 我不知道这是否意味着您的进程间通信具有相当大的数据要求) 。但是,您将获得所需的内存行为。请注意,如果生成相同的 JVM二进制映像,操作系统不应复制实际JVM消耗的内存。
答案 4 :(得分:0)
你应该看看分页是如何工作的。如果内存小于getpagesize(),则无法返回内存。