java - 使用 GC 中报告的实时验证单核上的 cpu 争用?
问题描述
我有一个ARMv7 Cortex-A8 (1 Core , 13-pipeline depth)
运行超过 250 个线程的 512M 设备;然而,顶级命令的平均负载似乎低于 1 或略高于 1.5 [1]。
在使用 vmstat[2] 时,我可以看到与设备 [2] 上可用的内核相比,procs(r) 似乎经常非常高,在这种情况下,它只是一个单核 cpu。
在设备上运行的进程之一上分析 GC 收集时,我得到以下 [3]:有趣的是,与(用户 + 系统)时间相比,实时性明显更高;因此,例如,据报道 GC 需要 226 毫秒,而实时则需要 230 毫秒。
鉴于以下情况:假设设备正遭受 cpu 争用是否正确,那么 CPU 争用是否会反映在使用 top 的平均负载中?顶部的平均负载是线程引起的 cpu 争用的一个很好的指标吗?还有什么可能导致 vmstat 的 procs -r 计数值偏高?
[3]
2019-01-21T10:18:55.607+0000: 78.012: [GC (Allocation Failure) 2019-01-21T10:18:55.608+0000: 78.013: [DefNew: 5632K->576K(5632K), 0.2220500 secs] 13789K->9541K(17928K), 0.2260043 secs] [Times: user=0.06 sys=0.00, real=0.23 secs]
2019-01-21T10:26:18.394+0000: 520.799: [GC (Allocation Failure) 2019-01-21T10:26:18.396+0000: 520.801: [DefNew: 9423K->601K(9792K), 0.1988650 secs] 30450K->21806K(31360K), 0.2060742 secs] [Times: user=0.07 sys=0.00, real=0.21 secs]
2019-01-21T10:19:51.661+0000: 134.066: [GC (Allocation Failure) 2019-01-21T10:19:51.663+0000: 134.068: [DefNew: 9560K->766K(9792K), 0.3196409 secs] 22499K->13926K(31360K), 0.3309429 secs] [Times: user=0.04 sys=0.02, real=0.33 secs]
[1]
//Top
top - 10:40:04 up 1:58, 8 users, load average: 1.66, 1.23, 1.64
Threads: 251 total, 3 running, 248 sleeping, 0 stopped, 0 zombie
[2]
Vmsatat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
5 0 0 16136 22012 232432 0 0 0 0 1614 3670 40 35 26 0 0
3 0 0 21740 22012 232444 0 0 0 0 2576 5744 61 39 0 0 0
0 0 0 21628 22012 232448 0 0 0 0 2006 4809 52 22 26 0 0
0 0 0 21740 22012 232448 0 0 0 0 595 843 5 8 87 0 0
3 0 0 21740 22012 232448 0 0 0 0 140 309 2 4 94 0 0
0 0 0 21740 22036 232448 0 0 0 116 220 349 8 3 89 0 0
2 0 0 21740 22036 232448 0 0 0 0 125 282 2 3 95 0 0
0 0 0 21740 22036 232448 0 0 0 0 129 280 2 4 94 0 0
1 0 0 21740 22036 232448 0 0 0 0 127 266 3 3 94 0 0
0 0 0 21740 22036 232448 0 0 0 4 145 315 3 3 94 0 0
2 0 0 18988 22036 232448 0 0 0 0 1619 3888 43 38 19 0 0
2 0 0 24592 22040 232444 0 0 0 36 2315 5472 64 36 0 0 0
0 0 0 24480 22040 232444 0 0 0 0 1766 4273 51 23 26 0 0
0 0 0 24512 22040 232444 0 0 0 0 658 1033 6 7 87 0 0
0 0 0 24544 22040 232444 0 0 0 0 163 353 1 4 95 0 0
0 0 0 24544 22040 232444 0 0 0 0 122 242 3 3 94 0 0
1 0 0 24544 22040 232444 0 0 0 0 142 304 1 4 95 0 0
0 0 0 24544 22040 232444 0 0 0 0 137 294 2 4 94 0 0
0 0 0 24544 22040 232444 0 0 0 0 137 276 3 4 93 0 0
0 0 0 24544 22040 232444 0 0 0 0 134 308 3 2 95 0 0
9 0 0 19080 22040 232448 0 0 0 0 1952 4268 42 37 20 0 0
1 0 0 24460 22040 232456 0 0 0 0 2058 4523 65 35 0 0 0
2 0 0 24560 22040 232452 0 0 0 0 3057 7385 58 42 0 0 0
解决方案
Linux 平均负载表示(粗略地说)操作系统进程队列中处于 或(历史上)状态的进程或R
线程D
数W
。
平均负载
top
是线程引起的 CPU 争用的良好指标吗?
不必要。
- 它可能是由进程而不是线程引起的。
- 该
D
状态意味着进程正在等待“不可中断的”I/O:通常是文件系统操作。因此,如果您正在访问一个慢速文件系统(例如负载很重的网络文件服务器),则很可能会推高平均负载。
还有什么可能导致
vmstat
'sprocs -r
count 的高值?
根据vmstat
手动输入,该r
列实际上是处于R
状态的进程(或线程)的数量。该d
列是处于D
状态的进程数。请注意,这些是瞬时测量值,而不是平均值。
所以,答案是过程。
需要注意的另一件事是,JVM 可能会在运行 GC 时挂起所有应用程序线程(用于进程)。根据 GC 实现,此暂停可能在 GC 运行期间或仅针对某些阶段。
因此,您观察到 GC CPU 时间和时钟时间几乎相同并不意味着没有 CPU 争用。
相反,GC CPU 时间和时钟时间之间的主要差异并不一定意味着存在 CPU 争用(与应用程序线程或其他进程)。另一种可能性是争用(真实)内存页。即虚拟内存抖动。
推荐阅读
- c++ - libpng 输出不是预期的输出
- r - R中具有多个单词和特殊字符的词云
- php - php 函数实现覆盖不可为空的参数
- locust - 将数据从一个任务函数传递到另一个任务函数时出现问题,同时顺序任务一个接一个
- java - MongoDB 文档的 @Id 是 HashMap 的属性?
- javascript - 变量定义并用作方法参数,但值从未使用过,因此得到 ESLint Unused Variables
- swift - Swift:快速创建日期数组
- unit-testing - 如何在 Angular 5 jasmine/karma 测试用例的 beforeeach 中调用模拟服务
- spring-boot - 我需要为中型数据项目选择哪个分布式数据库
- rest - Swagger 2.0 将文件上传到不发送额外内容的 SP Online