我在一台 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'
会帮助你。