Repository navigation
jcmd jstat gc
ceragon edited this page Jun 29, 2022
·
5 revisions
| name | perf key | jvm var |
|---|---|---|
| S0C | sun.gc.generation.0.space.1.capacity | no used |
| S1C | sun.gc.generation.0.space.2.capacity | to_counters |
| S0U | sun.gc.generation.0.space.1.used | no used |
| S1U | sun.gc.generation.0.space.2.used | to_counters |
| EC | sun.gc.generation.0.space.0.capacity | eden_counters |
| EU | sun.gc.generation.0.space.0.used | eden_counters |
| OC | sun.gc.generation.1.space.0.capacity | old_space_counters |
| OU | sun.gc.generation.1.space.0.used | old_space_counters |
| MC | sun.gc.metaspace.capacity | |
| MU | sun.gc.metaspace.used | |
| CCSC | sun.gc.compressedclassspace.capacity | |
| CCSU | sun.gc.compressedclassspace.used | |
| YGC | sun.gc.collector.0.invocations | |
| YGCT | sun.gc.collector.0.time/sun.os.hrt.frequency | |
| FGC | sun.gc.collector.1.invocations | |
| FGCT | sun.gc.collector.1.time/sun.os.hrt.frequency | |
| CGC | sun.gc.collector.2.invocations | |
| CGCT | sun.gc.collector.2.time/sun.os.hrt.frequency | |
| GCT | (sun.gc.collector.0.time + sun.gc.collector.1.time + sun.gc.collector.2.time)/sun.os.hrt.frequency |
G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h) :
_g1h(g1h){
_young_collection_counters = new G1YoungGenerationCounters(this, "young");
const char* young_collection_name_space = _young_collection_counters->name_space();
// name "generation.0.space.2"
_from_counters = new HSpaceCounters(young_collection_name_space,
"s0", 1 /* ordinal */,
pad_capacity(0) /* max_capacity */,
pad_capacity(0) /* init_capacity */);
// name "generation.0.space.1"
_to_counters = new HSpaceCounters(young_collection_name_space,
"s1", 2 /* ordinal */,
pad_capacity(overall_reserved()) /* max_capacity */,
pad_capacity(survivor_space_committed()) /* init_capacity */);
// name "generation.0.space.0"
_eden_counters = new HSpaceCounters(young_collection_name_space,
"eden", 0 /* ordinal */,
pad_capacity(overall_reserved()) /* max_capacity */,
pad_capacity(eden_space_committed()) /* init_capacity */);
_old_collection_counters = new G1OldGenerationCounters(this, "old");
_old_space_counters = new HSpaceCounters(_old_collection_counters->name_space(),
"space", 0 /* ordinal */,
pad_capacity(overall_reserved()) /* max_capacity */,
pad_capacity(old_space_committed()) /* init_capacity */);
}
G1YoungGenerationCounters::G1YoungGenerationCounters(G1MonitoringSupport* g1mm,
const char* name)
: G1GenerationCounters(g1mm, name, 0 /* ordinal */, 3 /* spaces */,
G1MonitoringSupport::pad_capacity(0, 3) /* min_capacity */,
G1MonitoringSupport::pad_capacity(g1mm->young_gen_max(), 3),
G1MonitoringSupport::pad_capacity(0, 3) /* curr_capacity */) {
}
G1GenerationCounters::G1GenerationCounters(G1MonitoringSupport* g1mm,
const char* name,
int ordinal, int spaces,
size_t min_capacity,
size_t max_capacity,
size_t curr_capacity)
: GenerationCounters(name, ordinal, spaces, min_capacity,
max_capacity, curr_capacity), _g1mm(g1mm) {
}
GenerationCounters::GenerationCounters(const char* name,
int ordinal, int spaces,
size_t min_capacity, size_t max_capacity,
size_t curr_capacity)
: _virtual_space(NULL) {
initialize(name, ordinal, spaces, min_capacity, max_capacity, curr_capacity);
}
void GenerationCounters::initialize(const char* name, int ordinal, int spaces,
size_t min_capacity, size_t max_capacity,
size_t curr_capacity) {
// ordinal 的值是 0
const char* cns = PerfDataManager::name_space("generation", ordinal);
cname = PerfDataManager::counter_name(_name_space, "spaces");
PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_None, spaces, CHECK);
cname = PerfDataManager::counter_name(_name_space, "capacity");
_current_size = PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes,
curr_capacity, CHECK);
}G1OldGenerationCounters::G1OldGenerationCounters(G1MonitoringSupport* g1mm,
const char* name)
: G1GenerationCounters(g1mm, name, 1 /* ordinal */, 1 /* spaces */,
G1MonitoringSupport::pad_capacity(0) /* min_capacity */,
G1MonitoringSupport::pad_capacity(g1mm->old_gen_max()),
G1MonitoringSupport::pad_capacity(0) /* curr_capacity */) {
}G1GenerationCounters::G1GenerationCounters(G1MonitoringSupport* g1mm,
const char* name,
int ordinal, int spaces,
size_t min_capacity,
size_t max_capacity,
size_t curr_capacity)
: GenerationCounters(name, ordinal, spaces, min_capacity,
max_capacity, curr_capacity), _g1mm(g1mm) {
}void MetaspaceCounters::initialize_performance_counters() {
size_t min_capacity = 0;
_perf_counters = new MetaspacePerfCounters("metaspace", min_capacity,
capacity(), max_capacity(), used());
}void CompressedClassSpaceCounters::initialize_performance_counters() {
const char* ns = "compressedclassspace";
if (UseCompressedClassPointers) {
size_t min_capacity = 0;
_perf_counters = new MetaspacePerfCounters(ns, min_capacity, capacity(),
max_capacity(), used());
} else {
_perf_counters = new MetaspacePerfCounters(ns, 0, 0, 0, 0);
}
}G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h) :
_g1h(g1h){
// YGC
_incremental_collection_counters =
new CollectorCounters("G1 incremental collections", 0);
// FGC
_full_collection_counters =
new CollectorCounters("G1 stop-the-world full collections", 1);
// CGC
_conc_collection_counters =
new CollectorCounters("G1 stop-the-world phases", 2);
}CollectorCounters::CollectorCounters(const char* name, int ordinal) {
const char* cns = PerfDataManager::name_space("collector", ordinal);
strcpy(_name_space, cns);
cname = PerfDataManager::counter_name(_name_space, "invocations");
_invocations = PerfDataManager::create_counter(SUN_GC, cname,
PerfData::U_Events, CHECK);
// time 的单位应该是
cname = PerfDataManager::counter_name(_name_space, "time");
_time = PerfDataManager::create_counter(SUN_GC, cname, PerfData::U_Ticks,
CHECK);
}void StatSampler::create_misc_perfdata() {
// 频率的单位是纳秒,1 s = 10^9 ns
PerfDataManager::create_constant(SUN_OS, "hrt.frequency",
PerfData::U_Hertz, os::elapsed_frequency(),
CHECK);
}const jlong NANOSECS_PER_SEC = CONST64(1000000000);
jlong os::elapsed_frequency() {
// 10的9次方
return NANOSECS_PER_SEC; // nanosecond resolution
}class G1MonitoringSupport : public CHeapObj<mtGC> {
size_t _eden_committed;
size_t _eden_used;
size_t _survivor_committed;
size_t _survivor_used;
size_t _old_committed;
size_t _old_used;
size_t eden_space_committed() {
return _eden_committed;
}
size_t eden_space_used() {
return _eden_used;
}
size_t survivor_space_committed() {
return _survivor_committed;
}
size_t survivor_space_used() {
return _survivor_used;
}
size_t old_space_committed() {
return _old_committed;
}
size_t old_space_used() {
return _old_used;
}
};class G1CollectedHeap : public CollectedHeap {
size_t _summary_bytes_used;
};
size_t G1CollectedHeap::used_unlocked() const {
return _summary_bytes_used;
}void G1MonitoringSupport::update_sizes() {
recalculate_sizes();
eden_counters()->update_capacity(pad_capacity(eden_space_committed()));
eden_counters()->update_used(eden_space_used());
to_counters()->update_capacity(pad_capacity(survivor_space_committed()));
to_counters()->update_used(survivor_space_used());
old_space_counters()->update_capacity(pad_capacity(old_space_committed()));
old_space_counters()->update_used(old_space_used());
}
void G1MonitoringSupport::recalculate_sizes() {
// young 的当前 region 数量
uint young_list_length = _g1h->young_regions_count();
// survivor 的当前 region 数量
uint survivor_list_length = _g1h->survivor_regions_count();
// eden 的当前 region 数量
uint eden_list_length = young_list_length - survivor_list_length;
// young 的最大数量
uint young_list_max_length = _g1h->g1_policy()->young_list_max_length();
// eden 的最大数量 = young max - survivor size
uint eden_list_max_length = young_list_max_length - survivor_list_length;
_eden_used = (size_t) eden_list_length * HeapRegion::GrainBytes;
_survivor_used = (size_t) survivor_list_length * HeapRegion::GrainBytes;
// java 堆总使用空间
_overall_used = _g1h->used_unlocked();
// old used = 参数1 - 参数2 = 总使用空间 - eden used - survivor used
_old_used = subtract_up_to_zero(_overall_used, _eden_used + _survivor_used);
// survivor 的容量,因为 g1 的 survivor 没有实际的容量,只有虚拟的上限。所以默认认为 used == capacity
_survivor_committed = _survivor_used;
// 暂时设置为 old used
_old_committed = HeapRegion::align_up_to_region_byte_size(_old_used);
// g1 的当前容量(非物理的上限,除非 -Xms == -Xmx)
_overall_committed = _g1h->capacity();
size_t committed = _overall_committed;
// 目前的这个 committed 就是 all_commited - (survivor used + old used)
committed -= _survivor_committed + _old_committed;
// eden 的 capacity
_eden_committed = (size_t) eden_list_max_length * HeapRegion::GrainBytes;
_eden_committed = MIN2(_eden_committed, committed);
committed -= _eden_committed;
// 多出来的空间,分给 old
_old_committed += committed;
// 年轻代的整体容量 = eden capacity + survivor used
_young_gen_committed = _eden_committed + _survivor_committed;
_eden_used = MIN2(_eden_used, _eden_committed);
}java 堆的总使用空间
size_t G1CollectedHeap::used_unlocked() const {
return _summary_bytes_used;
}void G1CollectedHeap::decrease_used(size_t bytes) {
_summary_bytes_used -= bytes;
}
void G1CollectedHeap::set_used(size_t bytes) {
_summary_bytes_used = bytes;
}
void G1CollectedHeap::increase_used(size_t bytes) {
_summary_bytes_used += bytes;
}class G1MonitoringSupport : public CHeapObj<mtGC> {
size_t _eden_committed;
size_t _eden_used;
size_t eden_space_used() {
return _eden_used;
}
};
void G1MonitoringSupport::update_eden_size() {
recalculate_eden_size();
// 更新 eden used
eden_counters()->update_used(eden_space_used());
}
void G1MonitoringSupport::recalculate_eden_size() {
// 当前年轻代占用的 region 数量
uint young_region_num = _g1h->young_regions_count();
// _young_region_num: 旧值
if (young_region_num > _young_region_num) {
// 增长的数量
uint diff = young_region_num - _young_region_num;
// 实际的大小(不考虑 region 内的实际对象占用,默认认为整个 region 都占用了)
_eden_used += (size_t) diff * HeapRegion::GrainBytes;
// _eden_committed: 是 eden 区的容量
_eden_used = MIN2(_eden_used, _eden_committed);
// 记录 young_region 大小
_young_region_num = young_region_num;
}
}打印 gc 的具体值
$ jstat -gc 23216
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT CGC CGCT GCT
0.0 7168.0 0.0 7168.0 131072.0 92160.0 3704832.0 785227.9 357448.0 343382.1 45388.0 40007.2 743 6.652 0 0.000 276 6.103 12.755打印 gc 的百分比和 gc 的原因
$ jstat -gccause 23216
S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT LGCC GCC
0.00 100.00 14.96 21.17 96.19 88.31 763 6.851 0 0.000 290 6.373 13.224 G1 Evacuation Pause No GC打印 gc 的百分比
$ jstat -gcutil 23216
S0 S1 E O M CCS YGC YGCT FGC FGCT CGC CGCT GCT
0.00 100.00 84.73 21.42 96.21 88.39 776 7.008 0 0.000 300 6.642 13.649