简体   繁体   English

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

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

I have an issue with memory management in various operating systems.我在各种操作系统中遇到内存管理问题。

My program is a server that does some processing that could take a few GB of memory.我的程序是一个服务器,它执行一些可能需要几 GB 内存的处理。 After that, it releases most of the memory while it waits for a few hours until another request arrives.之后,它会在等待几个小时直到另一个请求到达时释放大部分内存。

On AIX and Solaris, I observe the following behavior,在 AIX 和 Solaris 上,我观察到以下行为,

When I free memory, the memory is not returned back to the operating system.当我释放内存时,内存不会返回给操作系统。 The amount of virtual memory used by a process always increases - never decreases.进程使用的虚拟内存量总是增加 - 永远不会减少。 The same is true for the physical memory, up to its limit.物理内存也是如此,直到它的极限。 Thus it appears that we use all this memory in sleep mode as well.因此,我们似乎也在睡眠模式下使用所有这些内存。

When this memory can be returned back to OS?这个内存什么时候可以归还给操作系统? How can I make it?我怎样才能做到?

Linux is different: it appears that is does return memory sometimes, but I'm not able to understand when and how. Linux 是不同的:它似乎有时确实会返回内存,但我无法理解何时以及如何返回。 I have for example a scenario in which the process before a request was 100MB, then 700MB at the peak, and after releasing all that it was down to 600MB.例如,我有一个场景,在请求之前的进程是 100MB,然后是峰值 700MB,在释放所有之后它下降到 600MB。 I don't understand it - if Linux gives back memory to the OS, why not all of it?我不明白 - 如果 Linux 将内存归还给操作系统,为什么不是全部?

The glibc library (which is normally used as the standard C library in Linux) can allocate memory in two ways - with sbrk() or with mmap(). glibc 库(通常用作 Linux 中的标准 C 库)可以通过两种方式分配内存 - 使用 sbrk() 或使用 mmap()。 It will use mmap() for large enough allocations.它将使用 mmap() 进行足够大的分配。

Memory allocated with sbrk() cannot easily be given up again (only in special cases, and as far as I know glibc doesn't even try).用 sbrk() 分配的内存不能轻易再次放弃(仅在特殊情况下,据我所知 glibc 甚至不会尝试)。 Memory allocated with mmap() can be returned using munmap().使用 mmap() 分配的内存可以使用 munmap() 返回。

If you depend on being able to return memory to the OS, you can use mmap() directly instead of malloc();如果您依赖能够将内存返回给操作系统,则可以直接使用 mmap() 而不是 malloc(); but this will become inefficient if you allocate lots of small blocks.但是如果你分配很多小块,这将变得效率低下。 You may need to implement your own pool allocator on top of mmap().您可能需要在 mmap() 之上实现自己的池分配器。

Most of the times, memory won't be returned to the system until the process terminates.大多数情况下,直到进程终止,内存才会返回给系统。 Depending on operating system and runtime library, memory might be given back to the system, but I don't know of any reliable way to make sure this will happen.根据操作系统和运行时库,内存可能会返还给系统,但我不知道有什么可靠的方法来确保这会发生。

If processing requires a few GB of memory, have your server wait for the request, then spawn a new process for processing the data - You can communicate with your server using pipes.如果处理需要几 GB 内存,请让您的服务器等待请求,然后生成一个新进程来处理数据 - 您可以使用管道与您的服务器进行通信。 When processing is done, return the result and terminate the spawned process.处理完成后,返回结果并终止生成的进程。

the way memory is allocated (and maybe given back to the OS) is in the libc, i assume.我假设内存分配(可能还给操作系统)的方式在 libc 中。 The Programming language / library stack you are using might be of reason for this.您使用的编程语言/库堆栈可能是造成这种情况的原因。

I assume glibc will return non-fragmented memory at the top of the heap.我假设 glibc 将返回堆顶部的非碎片内存。 Your process might allocate 10MB of data it will use all the time.您的进程可能会分配 10MB 的数据,它将一直使用。 After that, 500MB of data that is used in processing will be allocated.之后,将分配用于处理的 500MB 数据。 After that, a tiny fragment of data that is kept even after the processing (might be the result of the processing) is allocated.之后,即使在处理(可能是处理的结果)之后仍保留的一小部分数据被分配。 After that another 500MB is allocated Memory layout is:之后又分配了 500MB 内存布局是:

|10MB used|500 MB processing|1MB result|500MB processing| |10MB 已用|500MB 处理|1MB 结果|500MB 处理| = 1011 MB total = 1011 MB 总计

When the 1000MB are freed, the memory layout is当 1000MB 被释放时,内存布局是

|10MB used|500MB freed|1MB result|500 MB freed| |已使用 10MB|已释放 500MB|结果为 1MB|已释放 500MB| glibc might now return the memory at the end... |10MB used|500MB freed|1MB result| glibc 现在可能会在最后返回内存... |10MB 已使用|500MB 已释放|1MB 结果| = 511 MB "in use" also only 11MB of that is used. = 511 MB“使用中”也仅使用了 11MB。

I assume that is what happens, you'll need to do further research (seperate memory pools come to mind) to ensure all memory will be freed我认为这就是发生的事情,您需要做进一步的研究(想到单独的内存池)以确保所有内存都将被释放

I think the only reliable and portable way to do this is to spawn a spawn a new process to handle your request.我认为唯一可靠可移植的方法是生成一个新进程来处理您的请求。 Upon process exit the OS will reap all the associated memory.在进程退出时,操作系统将获得所有相关的内存。

Unfortunately you then have the inefficiencies related to spawning this process and inter-process communication (I note you're doing a lot of processing - I don't know if this implies that your inter-process communication has sizable data requirements).不幸的是,您会遇到与生成此进程和进程间通信相关的低效率(我注意到您正在进行大量处理 - 我不知道这是否意味着您的进程间通信具有大量数据需求)。 However you will get the memory behaviour you require.但是,您将获得所需的内存行为。 Note the OS shouldn't duplicate the memory consumed by the actual JVM, provided you spawn an identical JVM binary image.请注意,操作系统不应复制实际 JVM 消耗的内存,前提是您生成了相同的JVM 二进制映像。

You should looks how pagination works.你应该看看分页是如何工作的。 You can't return memory if it's less than getpagesize().如果内存小于 getpagesize(),则无法返回内存。

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

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