CMSのいくつかの学習について

5898 ワード

1.Full GC
CMSを使用する場合、promotion failedまたはconcurrent mode failureが発生すると、Full GCがトリガーされます.
下はコードでプレゼンテーションします.
(1)promotion failed、コードは以下の通りである.

public static void main(String[] args) throws Exception {
	BigObj o1 = new BigObj(1024 * 1024 * 2);
	BigObj o2 = new BigObj(1024 * 1024 * 2);
	BigObj o3 = new BigObj(1024 * 1024 * 2);
	System.out.println(">>> minor gc");
	BigObj o4 = new BigObj(1024 * 1024 * 2);
		
	TimeUnit.SECONDS.sleep(2);
		
	BigObj o5 = new BigObj(1024 * 1024 * 2);
	BigObj o6 = new BigObj(1024 * 1024 * 2);
	System.out.println(">>> promotion failed");
	BigObj o7 = new BigObj(1024 * 1024 * 2);
	TimeUnit.SECONDS.sleep(2);
}

private static class BigObj {
		
	private byte[] b;
		
	public BigObj(int c) {
		b = new byte[c];
	}
		
}

パラメータ:
-Xms20m -Xmx20m -Xmn10m -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCMSInitiatingOccupancyOnly

私はsun JDK 1.6.0 u 30 64ビットを使っています.
出力されたログには、次のように表示されます.
[GC 2.094: [ParNew: 6578K->6578K(9216K), 0.0000323 secs]2.094: [CMS: 6150K->8192K(10240K), 0.0145035 secs] 12728K->12449K(19456K), [CMS Perm : 3058K->3057K(21248K)], 0.0146291 secs] [Times: user=0.00 sys=0.02, real=0.01 secs]

(2)concurrent mode failure,コードは同じで,パラメータを以下に変更する.
-Xms20m -Xmx20m -Xmn10m -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

ログには次のように表示されます.
[GC 2.105: [ParNew: 6562K->6562K(9216K), 0.0000330 secs]2.105: [CMS2.108: [CMS-concurrent-mark: 0.004/0.004 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
 (concurrent mode failure): 6150K->8192K(10240K), 0.0173765 secs] 12712K->12449K(19456K), [CMS Perm : 3058K->3057K(21248K)], 0.0175193 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]

2.preclean
CMS GCはremarkの前にconcurrent abortable precleanの段階がある.
Edenの占有量が2 Mを超えると、このフェーズが実行され、Edenの占有量が50%を超えるまでremarkがトリガーされません.もちろんずっと続くわけではありませんが、5000ミリ秒を超えるEdenの占有率が50%を超えていない場合も、この段階を終了してremarkがトリガーされます.この3つのパラメータは、-X:CMSScheduleRemarkEdenSizeThreshold-X:CMSScheduleRemarkEdenPenetration-X:CMSMaxAbortablePrecleanTimeでそれぞれ設定できます.
(1)Eden占有量が2 Mを超えない場合:
コードは次のとおりです.

public static void main(String[] args) throws Exception {
	BigObj o1 = new BigObj(1024 * 1024 * 2);
	BigObj o2 = new BigObj(1024 * 1024 * 2);
	BigObj o3 = new BigObj(1024 * 1024 * 3);
	System.out.println(">>> minor gc");
	BigObj o4 = new BigObj(1024 * 1024 * 1);
	TimeUnit.SECONDS.sleep(2);
}

パラメータ:
-Xms20m -Xmx20m -Xmn10m -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps

ログには次のように表示されます.
2.116: [CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
2.116: [GC[YG occupancy: 1615 K (9216 K)]2.116: [Rescan (parallel) , 0.0001575 secs]2.117: [weak refs processing, 0.0000058 secs] [1 CMS-remark: 7174K(10240K)] 8790K(19456K), 0.0002273 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

(2)Edenの占有率が50%を超える:
コードは次のとおりです.

public static void main(String[] args) throws Exception {
	BigObj o1 = new BigObj(1024 * 1024 * 2);
	BigObj o2 = new BigObj(1024 * 1024 * 2);
	BigObj o3 = new BigObj(1024 * 1024 * 2);
	System.out.println(">>> minor gc");
	BigObj o4 = new BigObj(1024 * 1024 * 2);
	TimeUnit.SECONDS.sleep(2);

	BigObj o5 = new BigObj(1024 * 1024 * 3);
	TimeUnit.SECONDS.sleep(2);
}

同じパラメータ:
ログには次のように表示されます.
2.106: [CMS-concurrent-abortable-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
2.106: [GC[YG occupancy: 5546 K (9216 K)]2.106: [Rescan (parallel) , 0.0001678 secs]2.106: [weak refs processing, 0.0000058 secs] [1 CMS-remark: 6150K(10240K)] 11696K(19456K), 0.0002596 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

(3)Edenの占有率はまだ50%を超えておらず、持続時間は5000ミリ秒を超えている.
コードは次のとおりです.

public static void main(String[] args) throws Exception {
	BigObj o1 = new BigObj(1024 * 1024 * 2);
	BigObj o2 = new BigObj(1024 * 1024 * 2);
	BigObj o3 = new BigObj(1024 * 1024 * 2);
	System.out.println(">>> minor gc");
	BigObj o4 = new BigObj(1024 * 1024 * 2);
	TimeUnit.SECONDS.sleep(2);
		
	BigObj o5 = new BigObj(1024 * 1024 * 1);
	TimeUnit.SECONDS.sleep(7);
}

同じパラメータ:
ログには次のように表示されます.
CMS: abort preclean due to time 7.210: [CMS-concurrent-abortable-preclean: 0.076/5.093 secs] [Times: user=0.02 sys=0.00, real=5.10 secs] 
7.210: [GC[YG occupancy: 3498 K (9216 K)]7.210: [Rescan (parallel) , 0.0002051 secs]7.210: [weak refs processing, 0.0000054 secs] [1 CMS-remark: 6150K(10240K)] 9648K(19456K), 0.0002727 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

パラメータを追加する場合:-XX:CMSMaxAbortablePrecleanTime=3000
ログが次のようになります.
CMS: abort preclean due to time 5.127: [CMS-concurrent-abortable-preclean: 0.044/3.024 secs] [Times: user=0.01 sys=0.00, real=3.02 secs] 
5.127: [GC[YG occupancy: 3498 K (9216 K)]5.127: [Rescan (parallel) , 0.0001886 secs]5.127: [weak refs processing, 0.0000058 secs] [1 CMS-remark: 6150K(10240K)] 9648K(19456K), 0.0002634 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

他にもCMS c h e d u l e RemarkEdenPenetrationパラメータを試してみましたが、何の役にも立たないようですね.