Mercurial > hg > graal-jvmci-8
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 } |