hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
void
G1CollectorPolicy_BestRegionsFirst::choose_collection_set(
double target_pause_time_ms) {
{- -------------------------------------------
(1) 処理の開始時間を記録しておく.
(この初期値は使われているか??. 参照される前に次の更新がくるが... #TODO)
---------------------------------------- -}
// Set this here - in case we're not doing young collections.
double non_young_start_time_sec = os::elapsedTime();
{- -------------------------------------------
(1) G1CollectorPolicy::start_recording_regions() を呼んで, G1CollectorPolicy オブジェクト内のフィールドを初期化.
---------------------------------------- -}
start_recording_regions();
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
guarantee(target_pause_time_ms > 0.0,
err_msg("target_pause_time_ms = %1.6lf should be positive",
target_pause_time_ms));
guarantee(_collection_set == NULL, "Precondition");
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
double base_time_ms = predict_base_elapsed_time_ms(_pending_cards);
double predicted_pause_time_ms = base_time_ms;
double time_remaining_ms = target_pause_time_ms - base_time_ms;
{- -------------------------------------------
(1)
---------------------------------------- -}
// the 10% and 50% values are arbitrary...
if (time_remaining_ms < 0.10 * target_pause_time_ms) {
time_remaining_ms = 0.50 * target_pause_time_ms;
_within_target = false;
} else {
_within_target = true;
}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
// We figure out the number of bytes available for future to-space.
// For new regions without marking information, we must assume the
// worst-case of complete survival. If we have marking information for a
// region, we can bound the amount of live data. We can add a number of
// such regions, as long as the sum of the live data bounds does not
// exceed the available evacuation space.
size_t max_live_bytes = _g1->free_regions() * HeapRegion::GrainBytes;
size_t expansion_bytes =
_g1->expansion_regions() * HeapRegion::GrainBytes;
{- -------------------------------------------
(1) (フィールドの初期化)
---------------------------------------- -}
_collection_set_bytes_used_before = 0;
_collection_set_size = 0;
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
// Adjust for expansion and slop.
max_live_bytes = max_live_bytes + expansion_bytes;
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
HeapRegion* hr;
{- -------------------------------------------
(1) もし Young GC mode であれば (= G1Gen オプションが指定されていれば),
以下の if ブロックの中で collection set を設定する
(なお, fully young の場合は, 以下のブロック内で設定したものだけが collection set になる.
partially young の場合は, 以下のブロック内を抜けた後で
Old の HeapRegion も collection set に加えられる)
---------------------------------------- -}
if (in_young_gc_mode()) {
{- -------------------------------------------
(1.1) 処理の開始時間を記録しておく.
---------------------------------------- -}
double young_start_time_sec = os::elapsedTime();
{- -------------------------------------------
(1.1) (トレース出力)
---------------------------------------- -}
if (G1PolicyVerbose > 0) {
gclog_or_tty->print_cr("Adding %d young regions to the CSet",
_g1->young_list()->length());
}
{- -------------------------------------------
(1.1) (フィールドの初期化)
---------------------------------------- -}
_young_cset_length = 0;
_last_young_gc_full = full_young_gcs() ? true : false;
if (_last_young_gc_full)
++_full_young_pause_num;
else
++_partial_young_pause_num;
{- -------------------------------------------
(1)
---------------------------------------- -}
// The young list is laid with the survivor regions from the previous
// pause are appended to the RHS of the young list, i.e.
// [Newly Young Regions ++ Survivors from last pause].
{- -------------------------------------------
(1.1) young_list 中のすべての survivor_region に対して,
HeapRegion::set_young() を呼び出して
_young_type フィールドを Young にしておく.
(終わったら, YoungList::clear_survivors() を呼んで
young_list 中の survivor に関するフィールドはリセットしておく)
---------------------------------------- -}
hr = _g1->young_list()->first_survivor_region();
while (hr != NULL) {
assert(hr->is_survivor(), "badly formed young list");
hr->set_young();
hr = hr->get_next_young_region();
}
// Clear the fields that point to the survivor list - they are
// all young now.
_g1->young_list()->clear_survivors();
{- -------------------------------------------
(1)
---------------------------------------- -}
if (_g1->mark_in_progress())
_g1->concurrent_mark()->register_collection_set_finger(_inc_cset_max_finger);
{- -------------------------------------------
(1.1) (フィールドの初期化)
---------------------------------------- -}
_young_cset_length = _inc_cset_young_index;
_collection_set = _inc_cset_head;
_collection_set_size = _inc_cset_size;
_collection_set_bytes_used_before = _inc_cset_bytes_used_before;
{- -------------------------------------------
(1.1) (変数宣言など)
---------------------------------------- -}
// For young regions in the collection set, we assume the worst
// case of complete survival
max_live_bytes -= _inc_cset_size * HeapRegion::GrainBytes;
time_remaining_ms -= _inc_cset_predicted_elapsed_time_ms;
predicted_pause_time_ms += _inc_cset_predicted_elapsed_time_ms;
{- -------------------------------------------
(1.1) (フィールドの更新)
---------------------------------------- -}
// The number of recorded young regions is the incremental
// collection set's current size
set_recorded_young_regions(_inc_cset_size);
set_recorded_rs_lengths(_inc_cset_recorded_rs_lengths);
set_recorded_young_bytes(_inc_cset_recorded_young_bytes);
#if PREDICTIONS_VERBOSE
set_predicted_bytes_to_copy(_inc_cset_predicted_bytes_to_copy);
#endif // PREDICTIONS_VERBOSE
{- -------------------------------------------
(1.1) (トレース出力)
---------------------------------------- -}
if (G1PolicyVerbose > 0) {
gclog_or_tty->print_cr(" Added " PTR_FORMAT " Young Regions to CS.",
_inc_cset_size);
gclog_or_tty->print_cr(" (" SIZE_FORMAT " KB left in heap.)",
max_live_bytes/K);
}
{- -------------------------------------------
(1.1) (assert)
---------------------------------------- -}
assert(_inc_cset_size == _g1->young_list()->length(), "Invariant");
{- -------------------------------------------
(1.1) 時間の計測処理
---------------------------------------- -}
double young_end_time_sec = os::elapsedTime();
_recorded_young_cset_choice_time_ms =
(young_end_time_sec - young_start_time_sec) * 1000.0;
{- -------------------------------------------
(1.1) (変数宣言など)
---------------------------------------- -}
// We are doing young collections so reset this.
non_young_start_time_sec = young_end_time_sec;
{- -------------------------------------------
(1.1) もし今回の GC が fully young と指定されていれば (かつ collection set が空でなければ),
collection set 選びはここで終了.
(choose_collection_set_end ラベルまでジャンプする)
---------------------------------------- -}
// Note we can use either _collection_set_size or
// _young_cset_length here
if (_collection_set_size > 0 && _last_young_gc_full) {
// don't bother adding more regions...
goto choose_collection_set_end;
}
}
{- -------------------------------------------
(1) もし Young GC mode でないか, もしくは Full Young GC mode でなければ,
以下の if ブロック内で Old 領域相当の region も collection set に追加する.
---------------------------------------- -}
if (!in_young_gc_mode() || !full_young_gcs()) {
{- -------------------------------------------
(1.1) (変数宣言など)
---------------------------------------- -}
bool should_continue = true;
NumberSeq seq;
double avg_prediction = 100000000000000000.0; // something very large
{- -------------------------------------------
(1.1) 以下, should_continue が true である限り, collection set に HeapRegion を追加し続ける.
終了するのは, 以下のどれかが成り立った場合.
* CollectionSetChooser::getNextMarkedRegion() の返り値が NULL だった.
* adaptive_young_list_length() が true で, かつ time_remaining_ms が 0 以下.
* adaptive_young_list_length() が false で, かつ collection set 内の個数が _young_list_fixed_length 以上.
---------------------------------------- -}
do {
{- -------------------------------------------
(1.1.1) CollectionSetChooser::getNextMarkedRegion() で, 最も適切な HeapRegion を取得.
---------------------------------------- -}
hr = _collectionSetChooser->getNextMarkedRegion(time_remaining_ms,
avg_prediction);
{- -------------------------------------------
(1.1.1) (なお, 以下の処理は CollectionSetChooser::getNextMarkedRegion() の返り値が NULL だった場合は行われない)
---------------------------------------- -}
if (hr != NULL) {
{- -------------------------------------------
(1.1.1) G1CollectorPolicy::predict_region_elapsed_time_ms() を呼んで, 処理にかかる時間を予測.
(その分の時間は, 局所変数である predicted_pause_time_ms や time_remaining_ms に足し込まれる)
---------------------------------------- -}
double predicted_time_ms = predict_region_elapsed_time_ms(hr, false);
time_remaining_ms -= predicted_time_ms;
predicted_pause_time_ms += predicted_time_ms;
{- -------------------------------------------
(1.1.1) G1CollectorPolicy::add_to_collection_set() を呼んで,
対象の HeapRegion を Collection Set に追加する.
---------------------------------------- -}
add_to_collection_set(hr);
{- -------------------------------------------
(1.1.1)
---------------------------------------- -}
record_non_young_cset_region(hr);
{- -------------------------------------------
(1.1.1) (トレース出力)
---------------------------------------- -}
max_live_bytes -= MIN2(hr->max_live_bytes(), max_live_bytes);
if (G1PolicyVerbose > 0) {
gclog_or_tty->print_cr(" (" SIZE_FORMAT " KB left in heap.)",
max_live_bytes/K);
}
{- -------------------------------------------
(1.1.1)
---------------------------------------- -}
seq.add(predicted_time_ms);
avg_prediction = seq.avg() + seq.sd();
}
{- -------------------------------------------
(1.1.1) もし以下の条件のどれかが成り立っていれば should_continue を false にする (= つまり, このループを終了する).
* CollectionSetChooser::getNextMarkedRegion() の返り値が NULL だった.
* adaptive_young_list_length() が true で, かつ time_remaining_ms が 0 以下.
* adaptive_young_list_length() が false で, かつ collection set 内の個数が _young_list_fixed_length 以上.
---------------------------------------- -}
should_continue =
( hr != NULL) &&
( (adaptive_young_list_length()) ? time_remaining_ms > 0.0
: _collection_set_size < _young_list_fixed_length );
} while (should_continue);
{- -------------------------------------------
(1.1) #TODO
上記のループを以下の条件で抜けた場合には, _should_revert_to_full_young_gcs フィールドを true にするようだが...
「adaptive_young_list_length() が false で, かつ collection set 内の個数が _young_list_fixed_length 以上の場合」
---------------------------------------- -}
if (!adaptive_young_list_length() &&
_collection_set_size < _young_list_fixed_length)
_should_revert_to_full_young_gcs = true;
}
{- -------------------------------------------
(1) (上記の "goto choose_collection_set_end" が実行された場合は, ここまでジャンプ)
---------------------------------------- -}
choose_collection_set_end:
{- -------------------------------------------
(1) (フィールドの更新)
---------------------------------------- -}
stop_incremental_cset_building();
{- -------------------------------------------
(1) G1CollectorPolicy::count_CS_bytes_used() を呼んで
collection set に選ばれた HeapRegion の合計使用量(HeapRegion::used())を計算し
フィールドに記録しておく.
---------------------------------------- -}
count_CS_bytes_used();
{- -------------------------------------------
(1) (フィールドの更新)
---------------------------------------- -}
end_recording_regions();
{- -------------------------------------------
(1) (フィールドの更新)
---------------------------------------- -}
double non_young_end_time_sec = os::elapsedTime();
_recorded_non_young_cset_choice_time_ms =
(non_young_end_time_sec - non_young_start_time_sec) * 1000.0;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.