Top


定義場所(file name)

hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp

名前(function name)

void
G1CollectorPolicy_BestRegionsFirst::choose_collection_set(
                                                  double target_pause_time_ms) {

本体部(body)

  {- -------------------------------------------
  (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.