我有一个进程,报告“顶部”,它有6GB的驻留内存和70GB的虚拟内存分配。 奇怪的是,这台服务器只有8GB的物理空间和35GB的交换空间。
从“顶部”手册:
o: VIRT -- Virtual Image (kb) The total amount of virtual memory used by the task. It includes all code, data and shared libraries plus pages that have been swapped out. (Note: you can define the STATSIZE=1 environment vari- able and the VIRT will be calculated from the /proc/#/state VmSize field.) VIRT = SWAP + RES.
给出这个解释,我期望一个进程的虚拟内存分配被限制在我的交换+物理内存可用。
根据'pmap',这个过程的代码,共享库和共享内存部分都是最小的 – 不超过300M左右。
显然,机器和过程仍然正常运行(虽然缓慢),所以我在这里错过了什么?
这可能是需求零内存不在物理ram中,或在页面文件中。
你可能想看一些资源:
你的应用程序是否创build了很多空的内存页面? 如果是这样的话,您的应用程序可能会从
它允许您在实时内存页面进行压缩和解压缩。 反过来,你可以保留所有内容,而不是交换到磁盘( 非常慢 )。
以下是关于virt与常驻记忆的讨论:
讨论涉及Java进程,但适用于在Linux下运行的任何东西。 关于virt的主要观点是总共包含了一大堆可能永远不会被使用的东西。 Virt是32位操作系统(因为进程将限制可寻址空间)的东西,但在其他方面基本上是无用的。 如上所述,要注意的是常驻内存,这将限于可用的物理内存和交换。
这可能是因为进程的地址空间与您所说的一样大小,但并不是由操作系统真正分配的。
来自: http : //lwn.net/Articles/428100/
在试图达到“开销足够低,没有明显延迟”这一目标的过程中,Go开发人员做了一些简化的假设,其中之一就是为正在运行的应用程序pipe理的内存来自单一的,实际上连续的地址范围。 这样的假设可能会遇到与编辑器碰到的vi相同的问题 – 其他代码可以在范围中间分配片断 – 所以Go开发人员采用相同的解决scheme:他们只是分配所有他们认为可能需要的内存(他们认为,合理地说,在启动时16GB应该足够在64位系统上)。
所以这就是内存pipe理有时候不好的方式 – 连续的地址空间简化了释放未使用的内存。
答案可能是MMAP – 数据在磁盘上,但在交换“外部”,不能用“空闲”或“顶部”命令看到。
如果java进程不是太复杂,你可以尝试使用“lsof”来查找MMAP文件的位置。 但是,如果这个java过程很复杂,就很难被看到。
我也感到惊讶的是,Linux允许你分配比物理内存+交换空间更多的虚拟内存,但显然它有助于在典型情况下的性能。
幸运的是,有一个内核调优参数可以用来切换记忆计费模式。 此参数是vm.overcommit_memory,它指示使用哪种algorithm来跟踪可用内存。 缺省值(0)使用启发式方法并过度提供虚拟内存系统。 如果您希望程序在分配时收到适当的内存不足错误,而不是使进程遭到随机杀害,则应将此参数设置为2。