使用 ps、top 和 free 了解 Linux 中正在发生的事情

使用 ps、top 和 free 了解 Linux 中正在发生的事情

我在一台 12 核 24 线程的机器上运行 Java 程序。它们有几个进程同时运行。看来我执行了太多进程,以至于整个任务使机器非常慢。

以下是热门信息

Tasks: 556 total,   2 running, 554 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.1%us,  0.4%sy,  0.0%ni, 63.2%id, 36.3%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:  16295248k total, 16169560k used,   125688k free,     3300k buffers
Swap: 18530296k total, 10867972k used,  7662324k free,    46188k cached

看来我的进程是内存消耗型的,所以几乎所有的内存都被它们使用了。在顶部信息中,我不明白为什么只有 2 个任务在运行,而不是 23 个(我已经调度了 23 个进程)。

free -g
             total       used       free     shared    buffers     cached
Mem:            15         15          0          0          0          0
-/+ buffers/cache:         15          0
Swap:           17         10          7

似乎所有内存都已被使用,并且交换导致机器速度变慢。

ps -e -o pid,%cpu,%mem,vsz,rss,comm= --sort=vsz
29707  5.6  4.2 6268732 685660 java
29712  5.2  3.9 6268732 647352 java
...
30269  3.2  4.3 6268732 704676 java
30334  4.8  4.2 6268732 689544 java

有 23 个这样的 java 进程。将所有 %cpu 加起来,非常接近 100%。但是 top 信息表明 CPU 并不繁忙。

Cpu(s):  0.1%us,  0.4%sy,  0.0%ni, 63.2%id, 36.3%wa,  0.0%hi,  0.0%si,  0.0%st

我谷歌了一下 vsz 和 rss 的大小,但没找到答案。我假设单位是千字节。观察 vsz,java 进程使用了​​ 6268732kb*23=144,180,836 =~ 144gb,这似乎不可能放入 RAM,因为它远远大于我的 RAM(16gb),所以只有 700000kb*23 =~ 16gb 被放入内存(带有 rss 信息,这是 RAM 中数据存储的部分)。由于频繁的交换和上下文切换导致系统变慢。

我不知道我的结论是否正确。请给我一些建议,以及我该如何解决这个问题。

添加更多细节:

vmstat -a -S M
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
 r  b   swpd   free  inact active   si   so    bi    bo   in   cs us sy id wa st
 2 29  16792    124   2105  13152    0    0    29    23    2    0  1  0 95  4  0

我不知道该如何解释 vmstat 数据。这有点奇怪,因为 swpd:使用的虚拟内存量看起来很高,而 si 和 so 为 0。

答案1

您的系统显然缺少 RAM。

  • 添加更多 RAM(希望你不需要添加至 128 GB)
  • 限制 JVM 实例的数量,因为每个实例使用 6 GB 虚拟内存。
  • 调整它们以使用更少的内存,这些是 64 位 JVM,看看 -Xmx 标志。

没有 CPU 问题。

答案2

你的结论确实是正确的。vsz 和 rss 的内存大小都是以 KB 为单位的,你可以查看 ps 的手册页,在标准格式说明符

您还可以执行另一项检查:rss(驻留集大小,IE每个进程使用的非交换内存(即每个进程使用的非交换内存)大约为 700MB。如果您有 23 个这样的进程,那么这足以说明 15GB 的已用内存(不是交换内存)。

此外,物理内存 + 交换空间的总大小远小于同时执行这 23 个任务所需的内存,前者为 16GB,后者为 144GB。因此,目前似乎没有一个进程分配到所需的内存量。

那么你有什么选择呢?只需一次运行两个进程,因为它们的大小足以让你将它们完全保存在内存中,而无需交换。完成后,再加载两个。这可以通过 bash 脚本轻松完成,使用命令等待

   my_job < file1.txt &
   my_job < file2.txt &
   wait 1 2
   my_job < file3.txt
   my_job < file4.txt
   wait 3 4....

这还将在内存中留下一些空间来保存 /tmp、/run 等,这意味着您的系统交互执行的能力将受到很小的影响。

第二种选择(也许是第一种),是问问自己,你是怎么得到 7GB 大小的 Java 代码的……但这是 StackOverflow 的问题

编辑:

我在这里回复 Marcus Thornton 的评论:

如果我能解决内存问题,...,一次性分派所有任务好吗?

是也不是。如果你解决了内存问题,那么你当然可以同时执行 2 个以上的作业。但你能执行 23 个吗?我认为你高估了多线程。多线程是单个处理器,具有两个执行上下文,允许在同一处理器上并行使用不同的功能单元。但如果任务相似的,正如您遇到的情况一样,它们很可能使用相同的功能单元,因此它们将像没有多线程一样排队。多线程与拥有独立处理器不同,它最多只能带来边际速度提升。

顺便问一下,你有多少个 CPU?你说的是处理器,而不是 CPU。以下命令

  /bin/cat /proc/cpuinfo | /bin/egrep 'processor|model name|cache size|core|sibling|physical'

会帮助你。

相关内容