在新的虚拟机上,top 显示我的一个进程消耗了 100 GB 的虚拟内存。我读过它是可能是因为过度使用不过,有点太过分了。我从未见过这样的事情,尤其是在只有 6 GB 实际内存、2 GB 交换空间和单个 40 GB 硬盘分区的虚拟机中。
具有 101 GB VIRT 的有趣进程是 Eclipse IDE(几分钟前开始),还有另一个,具有 98 GB VIRT 的 WebKitWebProcess。所有其他进程的 VIRT 值相同,约为 1-2 GB。所有这三个工具似乎都同意这一点:top
、htop
和ps
。
- 进程请求这么多虚拟内存有什么充分的理由吗?
- 这样的行为对系统来说不是有害的吗?
- 目前虚拟内存总量的限制是多少?
更新
详细信息:
Linux 4.15.0-38-generic x86_64 GNU/Linux、Linux Mint 19 Tara
Java HotSpot(TM) 64 位服务器 VM(内部版本 25.191-b12,混合模式)
版本:2018-09 (4.9.0) 内部版本 ID :20180917-1800
/proc//maps 的内容以
00400000-00401000 r-xp 00000000 08:01 132092 /usr/lib/jvm/java-8-oracle/jre/bin/java
00600000-00601000 r--p 00000000 08:01 132092 /usr/lib/jvm/java-8-oracle/jre/bin/java
00601000-00602000 rw-p 00001000 08:01 132092 /usr/lib/jvm/java-8-oracle/jre/bin/java
014fc000-02ebe000 rw-p 00000000 00:00 0 [heap]
c0000000-d0000000 rw-p 00000000 00:00 0
d0000000-100000000 ---p 00000000 00:00 0
100000000-1012c6000 rw-p 00000000 00:00 0
1012c6000-140000000 ---p 00000000 00:00 0
7ef800000000-7ef800004000 rw-p 00000000 00:00 0
7ef800004000-7ef8000ec000 rw-p 00000000 00:00 0
7ef8000ec000-7ef800100000 rw-p 00000000 00:00 0
7ef800100000-7f0800000000 rw-p 00000000 00:00 0
7f0800000000-7f1000000000 ---p 00000000 00:00 0
最后两行显示的行似乎是罪魁祸首0x7f0800000000 - 0x7ef800100000 ≈ 68.7e9
。据我所知,这是一个未映射的私有区域,没有权限。我只能说这么多......
答案1
最有可能的是它正在映射它可以索引的每个文件。我见过类似的 Kafka 映射数千个文件,但通常虚拟占用空间要高得多(~10 倍)。你可以运行:
cat /proc/{PID}/maps
(其中 {PID} 是您的 Eclipse 进程 ID)看看是否是这种情况。如果确实如此,如果您的虚拟足迹太大,您可能必须vm.max_map_count
加注。sysctl
答案2
每当映射文件时,操作系统都会分配一组连续的虚拟页面。
我不太了解 Java,但它很可能将每个新文件映射到一个新地址,该地址至少在 1Mb 边界(最肯定是 2Mb)对齐。
因此,如果一个非常小的文件(例如 64Kb)映射到内存中,它将在连续的虚拟页面中使用 2Mb 内存。使用足够的小文件来执行此操作,您的增长速度会比主要输入的速度快得多,因此可能会比您的磁盘和 RAM 更大。
此外,如果在某种调试模式下运行,大多数内存分配将会大得多。虽然可能不是你的情况。对于 C/C++,我们有一个由 Google 开发的系统,称为 sanitizer,它可以做到这一点。它允许您检测内存溢出(即在块开始之前或之后写入),并且它使用 MMU 来实现这一点(即,当在错误的位置写入内存时,您会得到硬件中断;读取没有得到很好的保护),这要求英特尔处理器上的缓冲区至少为 4K 边界。这些进程通常会在启动时使用大量内存,例如 20Tb。