部分转载:https://www.cnblogs.com/lsgxeva/p/10231201.html
性能指标
吞吐量:运行用户代码的时间占运行时间的比例
垃圾收集开销:垃圾收集器占总运行时间的比例
暂停时间:执行垃圾收集时,程序的工作线程被暂停的时间
收集频率:相对应用程序的执行,收集操作发生的频率
内存占用:java堆区所占内存的大小
现在常用的标准:在最大吞吐量优先的情况下,降低卡顿时间。
常见的收集器
G1收集器
目前服务端最常用的收集器是G1收集器
G1收集器的特点:
- 简单可行的性能调优
-XX:+UseG1GC -Xmx32g -XX:MaxGCPauseMillis=200
其中-XX:+UseG1GC为开启G1垃圾收集器,-Xmx32g 设计堆内存的最大内存为32G,-XX:MaxGCPauseMillis=200设置GC的最大暂停时间为200ms。
如果我们需要调优,在内存大小一定的情况下,我们只需要修改最大暂停时间即可。
-
G1将新生代,老年代的物理空间划分取消了。它将堆划分为若干个区域(Region),仍然属于分代收集器。
这些区域的一部分包含新生代,新生代的垃圾收集依然采用暂停所有应用线程的方式,将存活对象拷贝到老年代或者Survivor空间。老年代也分成很多区域,G1收集器通过将对象从一个区域复制到另外一个区域,完成了清理工作。 -
G1提供了两种GC模式,Young GC和Mixed GC,两种都是Stop The World(STW)。
Young GC
Young GC主要是对Eden区进行GC,它在Eden空间耗尽时会被触发。在这种情况下,Eden空间的数据移动到Survivor空间中,如果Survivor空间不够,Eden空间的部分数据会直接晋升到年老代空间。Survivor区的数据移动到新的Survivor区中,也有部分数据晋升到老年代空间中。最终Eden空间的数据为空,GC停止工作,应用线程继续执行。
具体过程如下:
- 根扫描:静态和本地对象被扫描
- 更新RS: 处理dirty card队列更新RS
- 处理RS检测从年轻代指向年老代的对象
- 对象拷贝 拷贝存活的对象到survivor/old区域
- 处理引用队列: 软引用,弱引用,虚引用处理
G1引进了RSet(Remembered Set)的概念来解决根扫描范围太广的问题。
引入卡表(Card table)来解决RSet的开销问题。
G1 Mix GC
Mix GC不仅进行正常的新生代垃圾收集,同时也回收部分后台扫描线程标记的老年代分区。
它的GC步骤分2步:
- 全局并发标记(global concurrent marking)
- 拷贝存活对象(evacuation)
G1调优
一些常用的参数:
-XX:+UseG1GC -Xmx32g -XX:MaxGCPauseMillis=200
GCPauseMillis最大暂停时间:能容忍的最大暂停时间是有一个限度的,我们需要在吞吐量和MaxGCPauseMillis之间做一个平衡。如果MaxGCPauseMillis设置的过小,那么GC就会频繁,吞吐量就会下降。如果MaxGCPauseMillis设置的过大,应用程序暂停时间就会变长。G1的默认暂停时间是200毫秒。
-XX:G1HeapRegionSize=n
设置的 G1 区域的大小。值是 2 的幂,范围是 1 MB 到 32 MB 之间。目标是根据最小的 Java 堆大小划分出约 2048 个区域。
-XX:ParallelGCThreads=n
设置 STW 工作线程数的值。将 n 的值设置为逻辑处理器的数量。n 的值与逻辑处理器的数量相同,最多为 8。
-XX:ConcGCThreads=n
设置并行标记的线程数。将 n 设置为并行垃圾回收线程数 (ParallelGCThreads) 的 1/4 左右。