comparison src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp @ 794:315a5d70b295

6484957: G1: parallel concurrent refinement 6826318: G1: remove traversal-based refinement code Summary: Removed traversal-based refinement code as it's no longer used. Made the concurrent refinement (queue-based) parallel. Reviewed-by: tonyp
author iveresov
date Mon, 11 May 2009 16:30:56 -0700
parents 20c6f43950b5
children 215f81b4d9b3
comparison
equal deleted inserted replaced
758:9b3a41ccc927 794:315a5d70b295
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 }