htop 显示的常驻内存使用量多于机器的内存使用量

htop shows more resident memory usage than what the machine has

htoptop 显示驻留内存消耗比机器上存在的物理内存更多:

htop 输出:

最高输出:

自由输出:

这怎么可能?

编辑 1:

pmap 输出:https://gist.github.com/ixaxaar/1571308666360f65dc66

一项快速实验表明,在 fork 之后,RES 将计算父进程和子进程的内存,尽管实际上每个页面都将共享,直到一个进程修改它或终止。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main ()
{
  /* 100 MiB */
  size_t size = 100 * 1024 * 1024;
  char *ptr = malloc (size);

  memset (ptr, 1, size);

  int pid = fork ();
  if (pid == 0)
  {
    puts ("Child");
  }
  else
  {
    puts ("Parent");
  }
  sleep (60);
  puts ("Bye");

  return 0;
}

如果我 运行 然后查看 htop,我看到两个驻留“100M”的进程。

正如您在评论中所写

we do a lot of mmap's

一个可能的解释是使用了 disk-based 个文件中的 mmap() 个。

复制者

首先,制作一个 2 GB 的文件(它也可以是一个稀疏文件,因此它实际上不会占用 2 GB 的磁盘空间):

truncate --size 2G 2-gb-file

现在,使用 Python:

映射它

test.py:

import mmap

file = "2-gb-file"

with open(file, "r+b") as f:
  mm = mmap.mmap(f.fileno(), 0)
  print("Reading file into memory...")
  mm.read()
  input("Press Enter to finish...")

运行 与 python3 test.py.

mm.read() 通过 运行 并且 return 值(在内存中读取 bytes)被 GC 后,您可以在 htop RES 比 system-global Mem 高得多(2057M vs 846M):

彩色屏幕截图:

文本中的相同屏幕截图:

  Mem[|||||||||||||||||||||                 846M/252G] Tasks: 62, 62 thr, 141 kthr; 1 running
  Swp[                                          0K/0K] Load average: 0.45 0.47 0.58 
                                                       Uptime: 89 days, 09:42:34

    PID USER      PRI  NI  VIRT   RES   SHR S CPU%▽MEM%  DISK READ     DISK R/W   TIME+  Command
2476802 root       20   0 2273M 2057M 2053M S  0.0  0.8    0.00 B/s    0.00 B/s  0:00.99 python3 test.py

说明

根据https://techtalk.intersec.com/2013/07/memory-part-2-understanding-process-memory/

RES is the resident set size, that is the amount of physical memory the kernel considers assigned to the process.

The resident set size is computed by the kernel as the sum of two counters. The first one contains the number of anonymous resident pages (MM_ANONPAGES), the second one is the number of file-backed resident pages (MM_FILEPAGES). Some pages may be considered as resident for more than one process at once, so the sum of the RES may be larger than the amount of RAM effectively used, or even larger than the amount of RAM available on the system.

在这个措辞中,“更大的系统 RAM 量”的理由是“一些页面可能被考虑用于多个进程”。

但是是否可以只用 单个 进程来创建这种情况?

是的!见下文。

单个进程使用的内存超过系统内存

让我们重复映射同一个文件,从不同的文件描述符到不同的内存映射。

这允许我们创造任意多RES:

import mmap

file = "2-gb-file"

open_files = []
mmaps = []

for i in range(200):
  print("Reading file into memory, iteration", i)
  f = open(file, "r+b")
  mm = mmap.mmap(f.fileno(), 0)
  mm.read()

  # Prevent GC of FD and mapping
  open_files.append(f)
  mmaps.append(mm)

input("Press Enter to finish...")

htop 显示此单个进程现在使用 400 GB RES 即使机器只有 252 GB RAM:

彩色屏幕截图:

文本中的相同屏幕截图:

  Mem[|||||||||||||||||||||                1.61G/252G] Tasks: 63, 62 thr, 141 kthr; 2 running
  Swp[                                          0K/0K] Load average: 1.47 0.87 0.68 
                                                       Uptime: 89 days, 09:49:37

    PID USER      PRI  NI  VIRT   RES   SHR S CPU%▽MEM%  DISK READ     DISK R/W   TIME+  Command
2477632 root       20   0  400G  400G  400G S  0.0 158.    0.00 B/s    0.00 B/s  3:10.91 python3 test.py

总结

是的,使用mmap我们可以使RES超过可用的物理内存。

没有必要为此使用多个进程。