看一段线上的gc日志,这是一段CMS步骤的日志,对于GC日志的完整格式,不了解的可以再温习一下《GC及JVM参数》
2017-07-18T21:28:41.422+0800: 11941915.242: [GC (CMS Initial Mark) [1 CMS-initial-mark: 786446K(1048576K)] 789098K(1992320K), 0.2623622 secs] [Times: user=0.00 sys=0.00, real=0.26 secs] 2017-07-18T21:28:41.684+0800: 11941915.505: Total time for which application threads were stopped: 0.2630097 seconds, Stopping threads took: 0.0000587 seconds 2017-07-18T21:28:41.685+0800: 11941915.505: [CMS-concurrent-mark-start] 2017-07-18T21:29:02.443+0800: 11941936.263: [CMS-concurrent-mark: 20.758/20.758 secs] [Times: user=3.22 sys=1.67, real=20.75 secs] 2017-07-18T21:29:02.443+0800: 11941936.263: [CMS-concurrent-preclean-start] 2017-07-18T21:29:02.502+0800: 11941936.322: [CMS-concurrent-preclean: 0.059/0.059 secs] [Times: user=0.02 sys=0.01, real=0.06 secs] 2017-07-18T21:29:02.502+0800: 11941936.322: [CMS-concurrent-abortable-preclean-start] CMS: abort preclean due to time 2017-07-18T21:29:07.600+0800: 11941941.420: [CMS-concurrent-abortable-preclean: 0.889/5.098 secs] [Times: user=1.72 sys=0.31, real=5.10 secs] 2017-07-18T21:29:07.602+0800: 11941941.422: Application time: 25.9175914 seconds 2017-07-18T21:29:07.603+0800: 11941941.423: [GC (CMS Final Remark) [YG occupancy: 491182 K (943744 K)] 2017-07-18T21:29:07.603+0800: 11941941.423: [Rescan (parallel) , 0.0654053 secs] 2017-07-18T21:29:07.668+0800: 11941941.488: [weak refs processing, 0.6491578 secs] 2017-07-18T21:29:08.317+0800: 11941942.138: [class unloading, 4.2229435 secs] 2017-07-18T21:29:12.540+0800: 11941946.361: [scrub symbol table, 0.0536739 secs] 2017-07-18T21:29:12.594+0800: 11941946.414: [scrub string table, 0.0009992 secs][1 CMS-remark: 786446K(1048576K)] 1277629K(1992320K), 5.0003976 secs] [Times: user=0.96 sys=0.01, real=5.00 secs] 2017-07-18T21:29:12.603+0800: 11941946.423: Total time for which application threads were stopped: 5.0011973 seconds, Stopping threads took: 0.0000483 seconds
至少一个步骤:
- 初始(CMS-initial-mark) ,会导致标记swt;
- 同时(CMS-concurrent-mark),与用户线程同时运行;
- 预清理(CMS-concurrent-preclean),与用户线程同时运行;
- 可被终止的预清理(CMS-concurrent-abortable-preclean) 与用户同时线程运行;
- 重新(CMS-remark) ,会导致swt;
- 同时清除(CMS-concurrent-sweep),与用户线程同时运行;
- 并发并发状态(CMS-reset),等待与用户线程同时运行;
通过
[Times: user=0.96 sys=0.01, real=5.00 secs]
STW 了 5s,对于一个 1110QPS 的系统台,那5500 万次服务,显示了这幅达不到高度可用的要求
对用户,系统,真正的,用户+系统的时间是通过实际的说明,而不是真正的,值的这种时间恰好在 cpu 执行,cpu 启动了
此时,可以通过sar命令查看一下
sar(System Activity Reporter 系统活动情况报告)是目前 Linux 上最全面的系统性能分析,可以从多方面对系统的活动进行报告,包括:文件的情况、系统调用的使用情况分析、石墨I/O、CPU效率及内存使用情况、进程活动IPC相关的活动等
sar -B 输出说明:
输出项说明:
pgpgin/s:表示内存内存或交换到替换到的字节数(KB)
pgpgout/s:表示从内存置换到磁盘或SWAP的字节数(KB)
fault/s:每一个系统产生的缺页数即主缺页与次缺页之和(主要+次要)
majflt/s:每两周的主缺页数。
pg免费/中的个数
pgscank/s:被亲切页的个个kswapd数
pgscand/s:个直接被扫描的页数
pgsteal/s:每秒钟从缓存中被清除来满足内存需要的页数
%vmeffste:清除的占总页(pgscank+pgscand)的清除的总页
交换
可以看到大量的pgin,这里就换一次linux的swap
Linux 将其物理 RAM(随机存取内存)划分为称为页面的内存块。交换是将内存页复制到硬盘上预先配置的空间(称为交换空间)以释放该内存页的过程。物理内存和交换空间的组合大小是可用的虚拟内存量。
当物理内存 (RAM) 已满时,会使用 Linux 中的交换空间。如果系统需要更多内存资源并且 RAM 已满,则内存中的非活动页面将被移至交换空间。虽然交换空间可以帮助具有少量 RAM 的机器,但不应将其视为更多 RAM 的替代品。交换空间位于硬盘驱动器上,其访问时间比物理内存慢。交换空间可以是专用交换分区(推荐)、交换文件或交换分区和交换文件的组合。
Linux内核为了提高这种效率与速度,在运行文件后在内存中进行缓存,部分内存就是Cache Memory(缓存内存)。即使你的程序结束,缓存内存也不会自动释放。这会导致你在 Linux 系统程序中发现当前的物理内存后,你会提供很少的物理内存变化。那些被释放的空间很长时间来自一些没有什么操作的程序,这些被释放的空间被临时保存到Swap空间中,等到那些程序要运行时,再从Swap中恢复到内存中的数据。 。这样,系统总是在物理内存的时候,才进行交换交换。
交换与虚拟内存
windows:虚拟内存
linux:swap分区
Windows 不会用虚拟内存来代替虚拟内存,而当 Linux 的物理内存改变时,Linux 将不使用虚拟内存(即使使用虚拟内存)
交换窗口的虚拟内存和任何不同的位置,Windows可以设置在windows的,默认是在C盘,可以在系统文件盘下面找到一个里。而linux独立一个位置,方便有什么继续存在的窗口的自动设置,把一些机器的内容替换掉的某种情况下,有剩余的东西再执行的某些情况下,有时间待一会儿,交换空间是计算机的一部分,是虚拟内存的一部分
为什么会停顿这么长时间呢?
- 堆内存分配多大,当gc时,确实需要很长时间
- 内存用时,使用了swap,在gc时,需要从swap加载到内存,映射
解决思路
对于这个原因,可以了解的方案:
- 部署小点,通过小而快的方式达到gc
- 定期检测旧代使用值,当快达到使用值时(旧代执行率大于50%)主动cms gc
主动Gc可能会影响服务,所以可能需要服务先下线,gc完,重新上线
参考资料
CMS垃圾回收器详解
GC 算法:实现