在一台几年前的机器上,Ubuntu 20.04.4 LTS。附件的输出截图top
让我感觉很奇怪:
我有一台普通的 PC(没什么特别的),有 16 GB 的 RAM,没有交换区。Discord 怎么会使用 40 GB,teams 13 GB,zulip 36 GB 的虚拟内存?我现在偶尔会遇到这台机器的内存管理问题;有时如果我使用一些名为 Lean 的软件,该软件使用大量线程,那么它会使机器无响应,我需要使用 SysRq 来恢复;我在任何其他具有类似规格的 Ubuntu 设备上运行 Lean 时都没有遇到这个问题。这台机器是不是出了什么问题?
编辑:有人要求我澄清问题是什么。问题是“我的机器经常随机停机;它变得没有响应,我必须让内核随机终止进程才能使其再次响应。我查看了屏幕截图中的数字(标准的知名应用程序占用了 40 GB 的虚拟内存),我发现有些东西非常奇怪。还有谁能证实top
他们的 Discord 占用了 40 GB 的虚拟内存?”。
答案1
虚拟内存和物理内存有很大区别。这篇维基文章可以给你一个很好的关于虚拟内存如何工作的概述,但它的要点是这样的:
虚拟内存是一种抽象的内存空间,包括物理存储和缓存存储。由于它由操作系统抽象,因此应用程序能够跨线程(有时与其他应用程序)共享库和其他对象。
虚拟内存的消耗量有时会让人感到困惑,原因正如您所指出的那样。从逻辑上讲,当您的系统只有 16GB 可用内存时,Discord 不可能使用 40GB 内存。但是,用于确定进程使用多少虚拟内存的计算方式更像是这样的:
已用内存 = 进程中每个线程报告的内存消耗
因此,假设一个进程以 8 个线程运行,系统可能会看到如下内容:
线 | 已报告内存 |
---|---|
1 | 590MB |
2 | 410MB |
3 | 200MB |
4 | 650MB |
5 | 150MB |
6 | 25MB |
7 | 40MB |
8 | 35MB |
全部的: | 2.1GB |
但是,每个线程都会共享一些相同的内存。线程 1、2 和 4 可能使用相同的 375MB 库,这会导致top
(和其他工具)显示使用了 1.65GB 的内存,而实际上只有 900MB:
线 | 已报告内存 | 实际的 |
---|---|---|
1 | 590MB | 590MB (590-0=590) |
2 | 410MB | 35MB (410-375=35) |
4 | 650MB | 275MB (650-375=275) |
全部的: | 1,650MB | 900MB |
当您运行使用数十或数百个线程的应用程序时,这种计算可能会迅速导致虚拟内存数字看起来比已安装的 RAM 数量高出一个数量级。对于设计良好的应用程序来说,这不是问题,而且 Linux 能够处理高达 16EB 的虚拟内存,因此,如果不运行具有以下特征的应用程序,您的系统几乎不可能达到这个数量百万每个线程都消耗相同的共享内存空间。
请注意,“内存使用量”的计算需要已报告线程使用的内存量。线程通常不知道它们与其他线程共享多少内存。
搞清楚这些数学问题后,我们来看一下你的问题:
为什么 Discord 使用 40GB、团队使用 13GB、zulip 使用 36GB 虚拟内存?
⇢ 见上文。我现在偶尔会遇到这台机器的内存管理问题;有时如果我使用某个名为 Lean 的软件,该软件使用大量线程,那么它会使机器无响应,我需要使用 SysRq 来恢复;我在任何其他具有类似规格的 Ubuntu 设备上运行 Lean 时都没有遇到这个问题。这台机器是否在某种程度上出了问题?
⇢ “很多” 是多少?Linux 对系统上可以运行的进程/线程总数有限制,您可以通过终端找到您计算机上的这个数字,如下所示:cat /proc/sys/kernel/threads-max
在我的个人笔记本电脑(联想 X1 Carbon,配备较旧的 Core i5 和 8GB RAM)上,我得到的值为
62361
。默认情况下,此数字的计算方式为内存页数除以 4。我不熟悉 Lean,但是,如果应用程序正在生成数万个线程并使操作系统不堪重负,以至于内核开始杀死线程,那么您可以暂时增加线程最大值,如下所示:
echo 131072 > /proc/sys/kernel/threads-max
单个用户可以创建的进程/线程数量也有一个总限制,因此,如果您确实要使用线程推动系统发展,那么您将需要检查
ulimit
和getrlimit
。
最后要说的是:
我有一台普通的 PC(没什么特别的),有 16GB 的 RAM,没有交换空间。
如果您运行的应用程序会产生数千个线程,那么缺少交换将会产生问题。如果目标是减少 SSD 磨损,那么没有交换将无济于事。您的应用程序仍然可以写入缓存和tmp
位置,这将要写入磁盘。具有数千个线程读取/写入缓存的系统与物理内存耗尽时使用交换的系统没有什么不同。如果您正在处理大量文件,则缺少交换也会产生问题,因为每个打开的文件都需要一点内存。
您的系统可能会受益于分配少量的交换空间,大概 4~8GB,以及vm.swappiness
介于两者之间的某个值5
,15
以确保系统尽可能多地使用 RAM。