繁体   English   中英

如何将内存从进程返回到操作系统

[英]How to return memory from process to the OS

我在各种操作系统中遇到内存管理问题。

我的程序是一个服务器,它执行一些可能需要几 GB 内存的处理。 之后,它会在等待几个小时直到另一个请求到达时释放大部分内存。

在 AIX 和 Solaris 上,我观察到以下行为,

当我释放内存时,内存不会返回给操作系统。 进程使用的虚拟内存量总是增加 - 永远不会减少。 物理内存也是如此,直到它的极限。 因此,我们似乎也在睡眠模式下使用所有这些内存。

这个内存什么时候可以归还给操作系统? 我怎样才能做到?

Linux 是不同的:它似乎有时确实会返回内存,但我无法理解何时以及如何返回。 例如,我有一个场景,在请求之前的进程是 100MB,然后是峰值 700MB,在释放所有之后它下降到 600MB。 我不明白 - 如果 Linux 将内存归还给操作系统,为什么不是全部?

glibc 库(通常用作 Linux 中的标准 C 库)可以通过两种方式分配内存 - 使用 sbrk() 或使用 mmap()。 它将使用 mmap() 进行足够大的分配。

用 sbrk() 分配的内存不能轻易再次放弃(仅在特殊情况下,据我所知 glibc 甚至不会尝试)。 使用 mmap() 分配的内存可以使用 munmap() 返回。

如果您依赖能够将内存返回给操作系统,则可以直接使用 mmap() 而不是 malloc(); 但是如果你分配很多小块,这将变得效率低下。 您可能需要在 mmap() 之上实现自己的池分配器。

大多数情况下,直到进程终止,内存才会返回给系统。 根据操作系统和运行时库,内存可能会返还给系统,但我不知道有什么可靠的方法来确保这会发生。

如果处理需要几 GB 内存,请让您的服务器等待请求,然后生成一个新进程来处理数据 - 您可以使用管道与您的服务器进行通信。 处理完成后,返回结果并终止生成的进程。

我假设内存分配(可能还给操作系统)的方式在 libc 中。 您使用的编程语言/库堆栈可能是造成这种情况的原因。

我假设 glibc 将返回堆顶部的非碎片内存。 您的进程可能会分配 10MB 的数据,它将一直使用。 之后,将分配用于处理的 500MB 数据。 之后,即使在处理(可能是处理的结果)之后仍保留的一小部分数据被分配。 之后又分配了 500MB 内存布局是:

|10MB 已用|500MB 处理|1MB 结果|500MB 处理| = 1011 MB 总计

当 1000MB 被释放时,内存布局是

|已使用 10MB|已释放 500MB|结果为 1MB|已释放 500MB| glibc 现在可能会在最后返回内存... |10MB 已使用|500MB 已释放|1MB 结果| = 511 MB“使用中”也仅使用了 11MB。

我认为这就是发生的事情,您需要做进一步的研究(想到单独的内存池)以确保所有内存都将被释放

我认为唯一可靠可移植的方法是生成一个新进程来处理您的请求。 在进程退出时,操作系统将获得所有相关的内存。

不幸的是,您会遇到与生成此进程和进程间通信相关的低效率(我注意到您正在进行大量处理 - 我不知道这是否意味着您的进程间通信具有大量数据需求)。 但是,您将获得所需的内存行为。 请注意,操作系统不应复制实际 JVM 消耗的内存,前提是您生成了相同的JVM 二进制映像。

你应该看看分页是如何工作的。 如果内存小于 getpagesize(),则无法返回内存。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM