hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
G1CollectorPolicy::G1CollectorPolicy() :
{- -------------------------------------------
(1) フィールドの初期化
---------------------------------------- -}
_parallel_gc_threads(G1CollectedHeap::use_parallel_gc_threads()
? ParallelGCThreads : 1),
_n_pauses(0),
_recent_CH_strong_roots_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
_recent_G1_strong_roots_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
_recent_evac_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
_recent_pause_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
_recent_rs_sizes(new TruncatedSeq(NumPrevPausesForHeuristics)),
_recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
_all_pause_times_ms(new NumberSeq()),
_stop_world_start(0.0),
_all_stop_world_times_ms(new NumberSeq()),
_all_yield_times_ms(new NumberSeq()),
_all_mod_union_times_ms(new NumberSeq()),
_summary(new Summary()),
#ifndef PRODUCT
_cur_clear_ct_time_ms(0.0),
_min_clear_cc_time_ms(-1.0),
_max_clear_cc_time_ms(-1.0),
_cur_clear_cc_time_ms(0.0),
_cum_clear_cc_time_ms(0.0),
_num_cc_clears(0L),
#endif
_region_num_young(0),
_region_num_tenured(0),
_prev_region_num_young(0),
_prev_region_num_tenured(0),
_aux_num(10),
_all_aux_times_ms(new NumberSeq[_aux_num]),
_cur_aux_start_times_ms(new double[_aux_num]),
_cur_aux_times_ms(new double[_aux_num]),
_cur_aux_times_set(new bool[_aux_num]),
_concurrent_mark_init_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
_concurrent_mark_remark_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
_concurrent_mark_cleanup_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
// <NEW PREDICTION>
_alloc_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_prev_collection_pause_end_ms(0.0),
_pending_card_diff_seq(new TruncatedSeq(TruncatedSeqLength)),
_rs_length_diff_seq(new TruncatedSeq(TruncatedSeqLength)),
_cost_per_card_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_fully_young_cards_per_entry_ratio_seq(new TruncatedSeq(TruncatedSeqLength)),
_partially_young_cards_per_entry_ratio_seq(
new TruncatedSeq(TruncatedSeqLength)),
_cost_per_entry_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_partially_young_cost_per_entry_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_cost_per_byte_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_cost_per_byte_ms_during_cm_seq(new TruncatedSeq(TruncatedSeqLength)),
_constant_other_time_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_other_cost_per_region_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_non_young_other_cost_per_region_ms_seq(
new TruncatedSeq(TruncatedSeqLength)),
_pending_cards_seq(new TruncatedSeq(TruncatedSeqLength)),
_scanned_cards_seq(new TruncatedSeq(TruncatedSeqLength)),
_rs_lengths_seq(new TruncatedSeq(TruncatedSeqLength)),
_pause_time_target_ms((double) MaxGCPauseMillis),
// </NEW PREDICTION>
_in_young_gc_mode(false),
_full_young_gcs(true),
_full_young_pause_num(0),
_partial_young_pause_num(0),
_during_marking(false),
_in_marking_window(false),
_in_marking_window_im(false),
_known_garbage_ratio(0.0),
_known_garbage_bytes(0),
_young_gc_eff_seq(new TruncatedSeq(TruncatedSeqLength)),
_recent_prev_end_times_for_all_gcs_sec(new TruncatedSeq(NumPrevPausesForHeuristics)),
_recent_CS_bytes_used_before(new TruncatedSeq(NumPrevPausesForHeuristics)),
_recent_CS_bytes_surviving(new TruncatedSeq(NumPrevPausesForHeuristics)),
_recent_avg_pause_time_ratio(0.0),
_num_markings(0),
_n_marks(0),
_n_pauses_at_mark_end(0),
_all_full_gc_times_ms(new NumberSeq()),
// G1PausesBtwnConcMark defaults to -1
// so the hack is to do the cast QQQ FIXME
_pauses_btwn_concurrent_mark((size_t)G1PausesBtwnConcMark),
_n_marks_since_last_pause(0),
_initiate_conc_mark_if_possible(false),
_during_initial_mark_pause(false),
_should_revert_to_full_young_gcs(false),
_last_full_young_gc(false),
_prev_collection_pause_used_at_end_bytes(0),
_collection_set(NULL),
_collection_set_size(0),
_collection_set_bytes_used_before(0),
// Incremental CSet attributes
_inc_cset_build_state(Inactive),
_inc_cset_head(NULL),
_inc_cset_tail(NULL),
_inc_cset_size(0),
_inc_cset_young_index(0),
_inc_cset_bytes_used_before(0),
_inc_cset_max_finger(NULL),
_inc_cset_recorded_young_bytes(0),
_inc_cset_recorded_rs_lengths(0),
_inc_cset_predicted_elapsed_time_ms(0.0),
_inc_cset_predicted_bytes_to_copy(0),
#ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away
#pragma warning( disable:4355 ) // 'this' : used in base member initializer list
#endif // _MSC_VER
_short_lived_surv_rate_group(new SurvRateGroup(this, "Short Lived",
G1YoungSurvRateNumRegionsSummary)),
_survivor_surv_rate_group(new SurvRateGroup(this, "Survivor",
G1YoungSurvRateNumRegionsSummary)),
// add here any more surv rate groups
_recorded_survivor_regions(0),
_recorded_survivor_head(NULL),
_recorded_survivor_tail(NULL),
_survivors_age_table(true),
_gc_overhead_perc(0.0)
{
{- -------------------------------------------
(1) HeapRegion::setup_heap_region_size() 及び HeapRegionRemSet::setup_remset_size() を呼んで,
G1GC に関するコマンドラインオプションの値を調整しておく.
---------------------------------------- -}
// Set up the region size and associated fields. Given that the
// policy is created before the heap, we have to set this up here,
// so it's done as soon as possible.
HeapRegion::setup_heap_region_size(Arguments::min_heap_size());
HeapRegionRemSet::setup_remset_size();
{- -------------------------------------------
(1) YoungPLABSize と OldPLABSize の値を確かめておく.
(HeapRegion::GrainWords を超えているようなら, ここで異常終了させる)
---------------------------------------- -}
// Verify PLAB sizes
const uint region_size = HeapRegion::GrainWords;
if (YoungPLABSize > region_size || OldPLABSize > region_size) {
char buffer[128];
jio_snprintf(buffer, sizeof(buffer), "%sPLABSize should be at most %u",
OldPLABSize > region_size ? "Old" : "Young", region_size);
vm_exit_during_initialization(buffer);
}
{- -------------------------------------------
(1) フィールドの初期化
---------------------------------------- -}
_recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime());
_prev_collection_pause_end_ms = os::elapsedTime() * 1000.0;
_par_last_gc_worker_start_times_ms = new double[_parallel_gc_threads];
_par_last_ext_root_scan_times_ms = new double[_parallel_gc_threads];
_par_last_mark_stack_scan_times_ms = new double[_parallel_gc_threads];
_par_last_update_rs_times_ms = new double[_parallel_gc_threads];
_par_last_update_rs_processed_buffers = new double[_parallel_gc_threads];
_par_last_scan_rs_times_ms = new double[_parallel_gc_threads];
_par_last_obj_copy_times_ms = new double[_parallel_gc_threads];
_par_last_termination_times_ms = new double[_parallel_gc_threads];
_par_last_termination_attempts = new double[_parallel_gc_threads];
_par_last_gc_worker_end_times_ms = new double[_parallel_gc_threads];
_par_last_gc_worker_times_ms = new double[_parallel_gc_threads];
// start conservatively
_expensive_region_limit_ms = 0.5 * (double) MaxGCPauseMillis;
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
// <NEW PREDICTION>
int index;
if (ParallelGCThreads == 0)
index = 0;
else if (ParallelGCThreads > 8)
index = 7;
else
index = ParallelGCThreads - 1;
{- -------------------------------------------
(1) フィールドの初期化
---------------------------------------- -}
_pending_card_diff_seq->add(0.0);
_rs_length_diff_seq->add(rs_length_diff_defaults[index]);
_cost_per_card_ms_seq->add(cost_per_card_ms_defaults[index]);
_fully_young_cards_per_entry_ratio_seq->add(
fully_young_cards_per_entry_ratio_defaults[index]);
_cost_per_entry_ms_seq->add(cost_per_entry_ms_defaults[index]);
_cost_per_byte_ms_seq->add(cost_per_byte_ms_defaults[index]);
_constant_other_time_ms_seq->add(constant_other_time_ms_defaults[index]);
_young_other_cost_per_region_ms_seq->add(
young_other_cost_per_region_ms_defaults[index]);
_non_young_other_cost_per_region_ms_seq->add(
non_young_other_cost_per_region_ms_defaults[index]);
// </NEW PREDICTION>
{- -------------------------------------------
(1) (以下で, GC 停止時間の目標値(MaxGCPauseMillis) や
GC 実行間隔の目標値(GCPauseIntervalMillis)について
値のチェックや計算を行う)
(なおコメントによると,
目標値が指定されてなかった場合は, 最も柔軟性が高くなるように
GCPauseIntervalMillis は MaxGCPauseMillis+1 に設定している
(つまり MaxGCPauseMillis を GCPauseIntervalMillis を超えない範囲で最大限に大きくしている).
この値が嫌なユーザーは明示的に GCPauseIntervalMillis を指定しないといけない,
とのこと)
---------------------------------------- -}
// Below, we might need to calculate the pause time target based on
// the pause interval. When we do so we are going to give G1 maximum
// flexibility and allow it to do pauses when it needs to. So, we'll
// arrange that the pause interval to be pause time target + 1 to
// ensure that a) the pause time target is maximized with respect to
// the pause interval and b) we maintain the invariant that pause
// time target < pause interval. If the user does not want this
// maximum flexibility, they will have to set the pause interval
// explicitly.
{- -------------------------------------------
(1.1) まず MaxGCPauseMillis や GCPauseIntervalMillis の値を確かめておく.
以下のどちらかが成り立てば, ここで異常終了させる.
* MaxGCPauseMillis オプションが明示的に指定されているが, その値が 1 未満だった場合:
* GCPauseIntervalMillis オプションが明示的に指定されているが, その値が 1 未満だった場合:
---------------------------------------- -}
// First make sure that, if either parameter is set, its value is
// reasonable.
if (!FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
if (MaxGCPauseMillis < 1) {
vm_exit_during_initialization("MaxGCPauseMillis should be "
"greater than 0");
}
}
if (!FLAG_IS_DEFAULT(GCPauseIntervalMillis)) {
if (GCPauseIntervalMillis < 1) {
vm_exit_during_initialization("GCPauseIntervalMillis should be "
"greater than 0");
}
}
{- -------------------------------------------
(1.1) 次に, MaxGCPauseMillis オプションが指定されていなかった場合は 200 に初期化する.
(ただし, GCPauseIntervalMillis オプションが指定されていた場合は,
MaxGCPauseMillis 無しで GCPauseIntervalMillis だけ指定というのは許可していないので,
異常終了させる)
---------------------------------------- -}
// Then, if the pause time target parameter was not set, set it to
// the default value.
if (FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
if (FLAG_IS_DEFAULT(GCPauseIntervalMillis)) {
// The default pause time target in G1 is 200ms
FLAG_SET_DEFAULT(MaxGCPauseMillis, 200);
} else {
// We do not allow the pause interval to be set without the
// pause time target
vm_exit_during_initialization("GCPauseIntervalMillis cannot be set "
"without setting MaxGCPauseMillis");
}
}
{- -------------------------------------------
(1.1) 次に, GCPauseIntervalMillis オプションが指定されてなかった場合には
MaxGCPauseMillis + 1 に初期化しておく.
---------------------------------------- -}
// Then, if the interval parameter was not set, set it according to
// the pause time target (this will also deal with the case when the
// pause time target is the default value).
if (FLAG_IS_DEFAULT(GCPauseIntervalMillis)) {
FLAG_SET_DEFAULT(GCPauseIntervalMillis, MaxGCPauseMillis + 1);
}
{- -------------------------------------------
(1.1) 最後に, MaxGCPauseMillis と GCPauseIntervalMillis の値を確かめておく
(MaxGCPauseMillis が GCPauseIntervalMillis 以上なら, ここで異常終了させる)
---------------------------------------- -}
// Finally, make sure that the two parameters are consistent.
if (MaxGCPauseMillis >= GCPauseIntervalMillis) {
char buffer[256];
jio_snprintf(buffer, 256,
"MaxGCPauseMillis (%u) should be less than "
"GCPauseIntervalMillis (%u)",
MaxGCPauseMillis, GCPauseIntervalMillis);
vm_exit_during_initialization(buffer);
}
{- -------------------------------------------
(1) フィールドの初期化
---------------------------------------- -}
double max_gc_time = (double) MaxGCPauseMillis / 1000.0;
double time_slice = (double) GCPauseIntervalMillis / 1000.0;
_mmu_tracker = new G1MMUTrackerQueue(time_slice, max_gc_time);
_sigma = (double) G1ConfidencePercent / 100.0;
// start conservatively (around 50ms is about right)
_concurrent_mark_init_times_ms->add(0.05);
_concurrent_mark_remark_times_ms->add(0.05);
_concurrent_mark_cleanup_times_ms->add(0.20);
_tenuring_threshold = MaxTenuringThreshold;
// if G1FixedSurvivorSpaceSize is 0 which means the size is not
// fixed, then _max_survivor_regions will be calculated at
// calculate_young_list_target_length during initialization
_max_survivor_regions = G1FixedSurvivorSpaceSize / HeapRegion::GrainBytes;
assert(GCTimeRatio > 0,
"we should have set it to a default value set_g1_gc_flags() "
"if a user set it to 0");
_gc_overhead_perc = 100.0 * (1.0 / (1.0 + GCTimeRatio));
{- -------------------------------------------
(1) G1CollectorPolicy::initialize_all() を呼んで,
残りの初期化を行う.
---------------------------------------- -}
initialize_all();
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.