htop 显示的常驻内存使用量多于机器的内存使用量
htop shows more resident memory usage than what the machine has
htop
和 top
显示驻留内存消耗比机器上存在的物理内存更多:
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
超过可用的物理内存。
没有必要为此使用多个进程。
htop
和 top
显示驻留内存消耗比机器上存在的物理内存更多:
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
超过可用的物理内存。
没有必要为此使用多个进程。