hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp
changeset 2881 74a1337e4acc
parent 2741 34e2a243d69a
child 2882 d508a8bac491
equal deleted inserted replaced
2748:986f111ef897 2881:74a1337e4acc
    28 // ======= Concurrent Mark Thread ========
    28 // ======= Concurrent Mark Thread ========
    29 
    29 
    30 // The CM thread is created when the G1 garbage collector is used
    30 // The CM thread is created when the G1 garbage collector is used
    31 
    31 
    32 ConcurrentG1RefineThread::
    32 ConcurrentG1RefineThread::
    33 ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r) :
    33 ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next, int worker_id) :
    34   ConcurrentGCThread(),
    34   ConcurrentGCThread(),
       
    35   _worker_id(worker_id),
       
    36   _active(false),
       
    37   _next(next),
    35   _cg1r(cg1r),
    38   _cg1r(cg1r),
    36   _started(false),
       
    37   _in_progress(false),
       
    38   _do_traversal(false),
       
    39   _vtime_accum(0.0),
    39   _vtime_accum(0.0),
    40   _co_tracker(G1CRGroup),
    40   _co_tracker(G1CRGroup),
    41   _interval_ms(5.0)
    41   _interval_ms(5.0)
    42 {
    42 {
    43   create_and_start();
    43   create_and_start();
    44 }
    44 }
    45 
    45 
    46 const long timeout = 200; // ms.
    46 void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
    47 
    47   G1CollectedHeap* g1h = G1CollectedHeap::heap();
    48 void ConcurrentG1RefineThread::traversalBasedRefinement() {
    48   G1CollectorPolicy* g1p = g1h->g1_policy();
    49   _cg1r->wait_for_ConcurrentG1Refine_enabled();
    49   if (g1p->adaptive_young_list_length()) {
    50   MutexLocker x(G1ConcRefine_mon);
    50     int regions_visited = 0;
    51   while (_cg1r->enabled()) {
    51 
    52     MutexUnlocker ux(G1ConcRefine_mon);
    52     g1h->young_list_rs_length_sampling_init();
    53     ResourceMark rm;
    53     while (g1h->young_list_rs_length_sampling_more()) {
    54     HandleMark   hm;
    54       g1h->young_list_rs_length_sampling_next();
    55 
    55       ++regions_visited;
    56     if (G1TraceConcurrentRefinement) {
    56 
    57       gclog_or_tty->print_cr("G1-Refine starting pass");
    57       // we try to yield every time we visit 10 regions
    58     }
    58       if (regions_visited == 10) {
       
    59         if (_sts.should_yield()) {
       
    60           _sts.yield("G1 refine");
       
    61           // we just abandon the iteration
       
    62           break;
       
    63         }
       
    64         regions_visited = 0;
       
    65       }
       
    66     }
       
    67 
       
    68     g1p->check_prediction_validity();
       
    69   }
       
    70 }
       
    71 
       
    72 void ConcurrentG1RefineThread::run() {
       
    73   initialize_in_thread();
       
    74   _vtime_start = os::elapsedVTime();
       
    75   wait_for_universe_init();
       
    76 
       
    77   _co_tracker.enable();
       
    78   _co_tracker.start();
       
    79 
       
    80   while (!_should_terminate) {
       
    81     DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
       
    82     // Wait for completed log buffers to exist.
       
    83     {
       
    84       MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
       
    85       while (((_worker_id == 0 && !dcqs.process_completed_buffers()) ||
       
    86               (_worker_id > 0 && !is_active())) &&
       
    87              !_should_terminate) {
       
    88          DirtyCardQ_CBL_mon->wait(Mutex::_no_safepoint_check_flag);
       
    89       }
       
    90     }
       
    91 
       
    92     if (_should_terminate) {
       
    93       return;
       
    94     }
       
    95 
       
    96     // Now we take them off (this doesn't hold locks while it applies
       
    97     // closures.)  (If we did a full collection, then we'll do a full
       
    98     // traversal.
    59     _sts.join();
    99     _sts.join();
    60     bool no_sleep = _cg1r->refine();
       
    61     _sts.leave();
       
    62     if (!no_sleep) {
       
    63       MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
       
    64       // We do this only for the timeout; we don't expect this to be signalled.
       
    65       CGC_lock->wait(Mutex::_no_safepoint_check_flag, timeout);
       
    66     }
       
    67   }
       
    68 }
       
    69 
       
    70 void ConcurrentG1RefineThread::queueBasedRefinement() {
       
    71   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
       
    72   // Wait for completed log buffers to exist.
       
    73   {
       
    74     MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
       
    75     while (!_do_traversal && !dcqs.process_completed_buffers() &&
       
    76            !_should_terminate) {
       
    77       DirtyCardQ_CBL_mon->wait(Mutex::_no_safepoint_check_flag);
       
    78     }
       
    79   }
       
    80 
       
    81   if (_should_terminate) {
       
    82     return;
       
    83   }
       
    84 
       
    85   // Now we take them off (this doesn't hold locks while it applies
       
    86   // closures.)  (If we did a full collection, then we'll do a full
       
    87   // traversal.
       
    88   _sts.join();
       
    89   if (_do_traversal) {
       
    90     (void)_cg1r->refine();
       
    91     switch (_cg1r->get_last_pya()) {
       
    92     case PYA_cancel: case PYA_continue:
       
    93       // Continue was caught and handled inside "refine".  If it's still
       
    94       // "continue" when we get here, we're done.
       
    95       _do_traversal = false;
       
    96       break;
       
    97     case PYA_restart:
       
    98       assert(_do_traversal, "Because of Full GC.");
       
    99       break;
       
   100     }
       
   101   } else {
       
   102     int n_logs = 0;
   100     int n_logs = 0;
   103     int lower_limit = 0;
   101     int lower_limit = 0;
   104     double start_vtime_sec; // only used when G1SmoothConcRefine is on
   102     double start_vtime_sec; // only used when G1SmoothConcRefine is on
   105     int prev_buffer_num; // only used when G1SmoothConcRefine is on
   103     int prev_buffer_num; // only used when G1SmoothConcRefine is on
       
   104     // This thread activation threshold
       
   105     int threshold = DCQBarrierProcessCompletedThreshold * _worker_id;
       
   106     // Next thread activation threshold
       
   107     int next_threshold = threshold + DCQBarrierProcessCompletedThreshold;
       
   108     int deactivation_threshold = MAX2<int>(threshold - DCQBarrierProcessCompletedThreshold / 2, 0);
   106 
   109 
   107     if (G1SmoothConcRefine) {
   110     if (G1SmoothConcRefine) {
   108       lower_limit = 0;
   111       lower_limit = 0;
   109       start_vtime_sec = os::elapsedVTime();
   112       start_vtime_sec = os::elapsedVTime();
   110       prev_buffer_num = (int) dcqs.completed_buffers_num();
   113       prev_buffer_num = (int) dcqs.completed_buffers_num();
   111     } else {
   114     } else {
   112       lower_limit = DCQBarrierProcessCompletedThreshold / 4; // For now.
   115       lower_limit = DCQBarrierProcessCompletedThreshold / 4; // For now.
   113     }
   116     }
   114     while (dcqs.apply_closure_to_completed_buffer(0, lower_limit)) {
   117     while (dcqs.apply_closure_to_completed_buffer(_worker_id, lower_limit)) {
   115       double end_vtime_sec;
   118       double end_vtime_sec;
   116       double elapsed_vtime_sec;
   119       double elapsed_vtime_sec;
   117       int elapsed_vtime_ms;
   120       int elapsed_vtime_ms;
   118       int curr_buffer_num;
   121       int curr_buffer_num = (int) dcqs.completed_buffers_num();
   119 
   122 
   120       if (G1SmoothConcRefine) {
   123       if (G1SmoothConcRefine) {
   121         end_vtime_sec = os::elapsedVTime();
   124         end_vtime_sec = os::elapsedVTime();
   122         elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
   125         elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
   123         elapsed_vtime_ms = (int) (elapsed_vtime_sec * 1000.0);
   126         elapsed_vtime_ms = (int) (elapsed_vtime_sec * 1000.0);
   124         curr_buffer_num = (int) dcqs.completed_buffers_num();
       
   125 
   127 
   126         if (curr_buffer_num > prev_buffer_num ||
   128         if (curr_buffer_num > prev_buffer_num ||
   127             curr_buffer_num > DCQBarrierProcessCompletedThreshold) {
   129             curr_buffer_num > next_threshold) {
   128           decreaseInterval(elapsed_vtime_ms);
   130           decreaseInterval(elapsed_vtime_ms);
   129         } else if (curr_buffer_num < prev_buffer_num) {
   131         } else if (curr_buffer_num < prev_buffer_num) {
   130           increaseInterval(elapsed_vtime_ms);
   132           increaseInterval(elapsed_vtime_ms);
   131         }
   133         }
   132       }
   134       }
   133 
   135       if (_worker_id == 0) {
   134       sample_young_list_rs_lengths();
   136         sample_young_list_rs_lengths();
       
   137       } else if (curr_buffer_num < deactivation_threshold) {
       
   138         // If the number of the buffer has fallen below our threshold
       
   139         // we should deactivate. The predecessor will reactivate this
       
   140         // thread should the number of the buffers cross the threshold again.
       
   141         MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
       
   142         deactivate();
       
   143         if (G1TraceConcurrentRefinement) {
       
   144           gclog_or_tty->print_cr("G1-Refine-deactivated worker %d", _worker_id);
       
   145         }
       
   146         break;
       
   147       }
   135       _co_tracker.update(false);
   148       _co_tracker.update(false);
       
   149 
       
   150       // Check if we need to activate the next thread.
       
   151       if (curr_buffer_num > next_threshold && _next != NULL && !_next->is_active()) {
       
   152         MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
       
   153         _next->activate();
       
   154         DirtyCardQ_CBL_mon->notify_all();
       
   155         if (G1TraceConcurrentRefinement) {
       
   156           gclog_or_tty->print_cr("G1-Refine-activated worker %d", _next->_worker_id);
       
   157         }
       
   158       }
   136 
   159 
   137       if (G1SmoothConcRefine) {
   160       if (G1SmoothConcRefine) {
   138         prev_buffer_num = curr_buffer_num;
   161         prev_buffer_num = curr_buffer_num;
   139         _sts.leave();
   162         _sts.leave();
   140         os::sleep(Thread::current(), (jlong) _interval_ms, false);
   163         os::sleep(Thread::current(), (jlong) _interval_ms, false);
   141         _sts.join();
   164         _sts.join();
   142         start_vtime_sec = os::elapsedVTime();
   165         start_vtime_sec = os::elapsedVTime();
   143       }
   166       }
   144       n_logs++;
   167       n_logs++;
   145     }
   168     }
   146     // Make sure we harvest the PYA, if any.
   169     _co_tracker.update(false);
   147     (void)_cg1r->get_pya();
       
   148   }
       
   149   _sts.leave();
       
   150 }
       
   151 
       
   152 void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
       
   153   G1CollectedHeap* g1h = G1CollectedHeap::heap();
       
   154   G1CollectorPolicy* g1p = g1h->g1_policy();
       
   155   if (g1p->adaptive_young_list_length()) {
       
   156     int regions_visited = 0;
       
   157 
       
   158     g1h->young_list_rs_length_sampling_init();
       
   159     while (g1h->young_list_rs_length_sampling_more()) {
       
   160       g1h->young_list_rs_length_sampling_next();
       
   161       ++regions_visited;
       
   162 
       
   163       // we try to yield every time we visit 10 regions
       
   164       if (regions_visited == 10) {
       
   165         if (_sts.should_yield()) {
       
   166           _sts.yield("G1 refine");
       
   167           // we just abandon the iteration
       
   168           break;
       
   169         }
       
   170         regions_visited = 0;
       
   171       }
       
   172     }
       
   173 
       
   174     g1p->check_prediction_validity();
       
   175   }
       
   176 }
       
   177 
       
   178 void ConcurrentG1RefineThread::run() {
       
   179   initialize_in_thread();
       
   180   _vtime_start = os::elapsedVTime();
       
   181   wait_for_universe_init();
       
   182 
       
   183   _co_tracker.enable();
       
   184   _co_tracker.start();
       
   185 
       
   186   while (!_should_terminate) {
       
   187     // wait until started is set.
       
   188     if (G1RSBarrierUseQueue) {
       
   189       queueBasedRefinement();
       
   190     } else {
       
   191       traversalBasedRefinement();
       
   192     }
       
   193     _sts.join();
       
   194     _co_tracker.update();
       
   195     _sts.leave();
   170     _sts.leave();
       
   171 
   196     if (os::supports_vtime()) {
   172     if (os::supports_vtime()) {
   197       _vtime_accum = (os::elapsedVTime() - _vtime_start);
   173       _vtime_accum = (os::elapsedVTime() - _vtime_start);
   198     } else {
   174     } else {
   199       _vtime_accum = 0.0;
   175       _vtime_accum = 0.0;
   200     }
   176     }
   238 void ConcurrentG1RefineThread::print() {
   214 void ConcurrentG1RefineThread::print() {
   239   gclog_or_tty->print("\"Concurrent G1 Refinement Thread\" ");
   215   gclog_or_tty->print("\"Concurrent G1 Refinement Thread\" ");
   240   Thread::print();
   216   Thread::print();
   241   gclog_or_tty->cr();
   217   gclog_or_tty->cr();
   242 }
   218 }
   243 
       
   244 void ConcurrentG1RefineThread::set_do_traversal(bool b) {
       
   245   _do_traversal = b;
       
   246 }