26 #include "gc/g1/concurrentG1Refine.hpp" |
26 #include "gc/g1/concurrentG1Refine.hpp" |
27 #include "gc/g1/g1CollectedHeap.inline.hpp" |
27 #include "gc/g1/g1CollectedHeap.inline.hpp" |
28 #include "gc/g1/g1GCPhaseTimes.hpp" |
28 #include "gc/g1/g1GCPhaseTimes.hpp" |
29 #include "gc/g1/g1StringDedup.hpp" |
29 #include "gc/g1/g1StringDedup.hpp" |
30 #include "gc/g1/workerDataArray.inline.hpp" |
30 #include "gc/g1/workerDataArray.inline.hpp" |
31 #include "memory/allocation.hpp" |
31 #include "memory/resourceArea.hpp" |
32 #include "logging/log.hpp" |
32 #include "logging/log.hpp" |
33 #include "runtime/timer.hpp" |
33 #include "runtime/timer.hpp" |
34 #include "runtime/os.hpp" |
34 #include "runtime/os.hpp" |
35 |
35 |
36 // Helper class for avoiding interleaved logging |
36 static const char* Indents[5] = {"", " ", " ", " ", " "}; |
37 class LineBuffer: public StackObj { |
|
38 |
|
39 private: |
|
40 static const int BUFFER_LEN = 1024; |
|
41 static const int INDENT_CHARS = 3; |
|
42 char _buffer[BUFFER_LEN]; |
|
43 int _indent_level; |
|
44 int _cur; |
|
45 |
|
46 void vappend(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0) { |
|
47 int res = vsnprintf(&_buffer[_cur], BUFFER_LEN - _cur, format, ap); |
|
48 if (res != -1) { |
|
49 _cur += res; |
|
50 } else { |
|
51 DEBUG_ONLY(warning("buffer too small in LineBuffer");) |
|
52 _buffer[BUFFER_LEN -1] = 0; |
|
53 _cur = BUFFER_LEN; // vsnprintf above should not add to _buffer if we are called again |
|
54 } |
|
55 } |
|
56 |
|
57 public: |
|
58 explicit LineBuffer(int indent_level): _indent_level(indent_level), _cur(0) { |
|
59 for (; (_cur < BUFFER_LEN && _cur < (_indent_level * INDENT_CHARS)); _cur++) { |
|
60 _buffer[_cur] = ' '; |
|
61 } |
|
62 } |
|
63 |
|
64 #ifndef PRODUCT |
|
65 ~LineBuffer() { |
|
66 assert(_cur == _indent_level * INDENT_CHARS, "pending data in buffer - append_and_print_cr() not called?"); |
|
67 } |
|
68 #endif |
|
69 |
|
70 void append(const char* format, ...) ATTRIBUTE_PRINTF(2, 3) { |
|
71 va_list ap; |
|
72 va_start(ap, format); |
|
73 vappend(format, ap); |
|
74 va_end(ap); |
|
75 } |
|
76 |
|
77 const char* to_string() { |
|
78 _cur = _indent_level * INDENT_CHARS; |
|
79 return _buffer; |
|
80 } |
|
81 }; |
|
82 |
|
83 static const char* Indents[4] = {"", " ", " ", " "}; |
|
84 |
37 |
85 G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : |
38 G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : |
86 _max_gc_threads(max_gc_threads) |
39 _max_gc_threads(max_gc_threads) |
87 { |
40 { |
88 assert(max_gc_threads > 0, "Must have some GC threads"); |
41 assert(max_gc_threads > 0, "Must have some GC threads"); |
89 |
42 |
90 _gc_par_phases[GCWorkerStart] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Start:", false, 2); |
43 _gc_par_phases[GCWorkerStart] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Start (ms):"); |
91 _gc_par_phases[ExtRootScan] = new WorkerDataArray<double>(max_gc_threads, "Ext Root Scanning:", true, 2); |
44 _gc_par_phases[ExtRootScan] = new WorkerDataArray<double>(max_gc_threads, "Ext Root Scanning (ms):"); |
92 |
45 |
93 // Root scanning phases |
46 // Root scanning phases |
94 _gc_par_phases[ThreadRoots] = new WorkerDataArray<double>(max_gc_threads, "Thread Roots:", true, 3); |
47 _gc_par_phases[ThreadRoots] = new WorkerDataArray<double>(max_gc_threads, "Thread Roots (ms):"); |
95 _gc_par_phases[StringTableRoots] = new WorkerDataArray<double>(max_gc_threads, "StringTable Roots:", true, 3); |
48 _gc_par_phases[StringTableRoots] = new WorkerDataArray<double>(max_gc_threads, "StringTable Roots (ms):"); |
96 _gc_par_phases[UniverseRoots] = new WorkerDataArray<double>(max_gc_threads, "Universe Roots:", true, 3); |
49 _gc_par_phases[UniverseRoots] = new WorkerDataArray<double>(max_gc_threads, "Universe Roots (ms):"); |
97 _gc_par_phases[JNIRoots] = new WorkerDataArray<double>(max_gc_threads, "JNI Handles Roots:", true, 3); |
50 _gc_par_phases[JNIRoots] = new WorkerDataArray<double>(max_gc_threads, "JNI Handles Roots (ms):"); |
98 _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray<double>(max_gc_threads, "ObjectSynchronizer Roots:", true, 3); |
51 _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray<double>(max_gc_threads, "ObjectSynchronizer Roots (ms):"); |
99 _gc_par_phases[FlatProfilerRoots] = new WorkerDataArray<double>(max_gc_threads, "FlatProfiler Roots:", true, 3); |
52 _gc_par_phases[FlatProfilerRoots] = new WorkerDataArray<double>(max_gc_threads, "FlatProfiler Roots (ms):"); |
100 _gc_par_phases[ManagementRoots] = new WorkerDataArray<double>(max_gc_threads, "Management Roots:", true, 3); |
53 _gc_par_phases[ManagementRoots] = new WorkerDataArray<double>(max_gc_threads, "Management Roots (ms):"); |
101 _gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray<double>(max_gc_threads, "SystemDictionary Roots:", true, 3); |
54 _gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray<double>(max_gc_threads, "SystemDictionary Roots (ms):"); |
102 _gc_par_phases[CLDGRoots] = new WorkerDataArray<double>(max_gc_threads, "CLDG Roots:", true, 3); |
55 _gc_par_phases[CLDGRoots] = new WorkerDataArray<double>(max_gc_threads, "CLDG Roots (ms):"); |
103 _gc_par_phases[JVMTIRoots] = new WorkerDataArray<double>(max_gc_threads, "JVMTI Roots:", true, 3); |
56 _gc_par_phases[JVMTIRoots] = new WorkerDataArray<double>(max_gc_threads, "JVMTI Roots (ms):"); |
104 _gc_par_phases[CMRefRoots] = new WorkerDataArray<double>(max_gc_threads, "CM RefProcessor Roots:", true, 3); |
57 _gc_par_phases[CMRefRoots] = new WorkerDataArray<double>(max_gc_threads, "CM RefProcessor Roots (ms):"); |
105 _gc_par_phases[WaitForStrongCLD] = new WorkerDataArray<double>(max_gc_threads, "Wait For Strong CLD:", true, 3); |
58 _gc_par_phases[WaitForStrongCLD] = new WorkerDataArray<double>(max_gc_threads, "Wait For Strong CLD (ms):"); |
106 _gc_par_phases[WeakCLDRoots] = new WorkerDataArray<double>(max_gc_threads, "Weak CLD Roots:", true, 3); |
59 _gc_par_phases[WeakCLDRoots] = new WorkerDataArray<double>(max_gc_threads, "Weak CLD Roots (ms):"); |
107 _gc_par_phases[SATBFiltering] = new WorkerDataArray<double>(max_gc_threads, "SATB Filtering:", true, 3); |
60 _gc_par_phases[SATBFiltering] = new WorkerDataArray<double>(max_gc_threads, "SATB Filtering (ms):"); |
108 |
61 |
109 _gc_par_phases[UpdateRS] = new WorkerDataArray<double>(max_gc_threads, "Update RS:", true, 2); |
62 _gc_par_phases[UpdateRS] = new WorkerDataArray<double>(max_gc_threads, "Update RS (ms):"); |
110 _gc_par_phases[ScanHCC] = new WorkerDataArray<double>(max_gc_threads, "Scan HCC:", true, 3); |
63 if (ConcurrentG1Refine::hot_card_cache_enabled()) { |
111 _gc_par_phases[ScanHCC]->set_enabled(ConcurrentG1Refine::hot_card_cache_enabled()); |
64 _gc_par_phases[ScanHCC] = new WorkerDataArray<double>(max_gc_threads, "Scan HCC (ms):"); |
112 _gc_par_phases[ScanRS] = new WorkerDataArray<double>(max_gc_threads, "Scan RS:", true, 2); |
65 } else { |
113 _gc_par_phases[CodeRoots] = new WorkerDataArray<double>(max_gc_threads, "Code Root Scanning:", true, 2); |
66 _gc_par_phases[ScanHCC] = NULL; |
114 _gc_par_phases[ObjCopy] = new WorkerDataArray<double>(max_gc_threads, "Object Copy:", true, 2); |
67 } |
115 _gc_par_phases[Termination] = new WorkerDataArray<double>(max_gc_threads, "Termination:", true, 2); |
68 _gc_par_phases[ScanRS] = new WorkerDataArray<double>(max_gc_threads, "Scan RS (ms):"); |
116 _gc_par_phases[GCWorkerTotal] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Total:", true, 2); |
69 _gc_par_phases[CodeRoots] = new WorkerDataArray<double>(max_gc_threads, "Code Root Scanning (ms):"); |
117 _gc_par_phases[GCWorkerEnd] = new WorkerDataArray<double>(max_gc_threads, "GC Worker End:", false, 2); |
70 _gc_par_phases[ObjCopy] = new WorkerDataArray<double>(max_gc_threads, "Object Copy (ms):"); |
118 _gc_par_phases[Other] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Other:", true, 2); |
71 _gc_par_phases[Termination] = new WorkerDataArray<double>(max_gc_threads, "Termination (ms):"); |
119 |
72 _gc_par_phases[GCWorkerTotal] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Total (ms):"); |
120 _update_rs_processed_buffers = new WorkerDataArray<size_t>(max_gc_threads, "Processed Buffers:", true, 3); |
73 _gc_par_phases[GCWorkerEnd] = new WorkerDataArray<double>(max_gc_threads, "GC Worker End (ms):"); |
|
74 _gc_par_phases[Other] = new WorkerDataArray<double>(max_gc_threads, "GC Worker Other (ms):"); |
|
75 |
|
76 _update_rs_processed_buffers = new WorkerDataArray<size_t>(max_gc_threads, "Processed Buffers:"); |
121 _gc_par_phases[UpdateRS]->link_thread_work_items(_update_rs_processed_buffers); |
77 _gc_par_phases[UpdateRS]->link_thread_work_items(_update_rs_processed_buffers); |
122 |
78 |
123 _termination_attempts = new WorkerDataArray<size_t>(max_gc_threads, "Termination Attempts:", true, 3); |
79 _termination_attempts = new WorkerDataArray<size_t>(max_gc_threads, "Termination Attempts:"); |
124 _gc_par_phases[Termination]->link_thread_work_items(_termination_attempts); |
80 _gc_par_phases[Termination]->link_thread_work_items(_termination_attempts); |
125 |
81 |
126 _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray<double>(max_gc_threads, "Queue Fixup:", true, 2); |
82 if (UseStringDeduplication) { |
127 _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray<double>(max_gc_threads, "Table Fixup:", true, 2); |
83 _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray<double>(max_gc_threads, "Queue Fixup (ms):"); |
128 |
84 _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray<double>(max_gc_threads, "Table Fixup (ms):"); |
129 _gc_par_phases[RedirtyCards] = new WorkerDataArray<double>(max_gc_threads, "Parallel Redirty:", true, 3); |
85 } else { |
130 _redirtied_cards = new WorkerDataArray<size_t>(max_gc_threads, "Redirtied Cards:", true, 3); |
86 _gc_par_phases[StringDedupQueueFixup] = NULL; |
|
87 _gc_par_phases[StringDedupTableFixup] = NULL; |
|
88 } |
|
89 |
|
90 _gc_par_phases[RedirtyCards] = new WorkerDataArray<double>(max_gc_threads, "Parallel Redirty (ms):"); |
|
91 _redirtied_cards = new WorkerDataArray<size_t>(max_gc_threads, "Redirtied Cards:"); |
131 _gc_par_phases[RedirtyCards]->link_thread_work_items(_redirtied_cards); |
92 _gc_par_phases[RedirtyCards]->link_thread_work_items(_redirtied_cards); |
132 |
93 |
133 _gc_par_phases[PreserveCMReferents] = new WorkerDataArray<double>(max_gc_threads, "Parallel Preserve CM Refs:", true, 3); |
94 _gc_par_phases[PreserveCMReferents] = new WorkerDataArray<double>(max_gc_threads, "Parallel Preserve CM Refs (ms):"); |
134 } |
95 } |
135 |
96 |
136 void G1GCPhaseTimes::note_gc_start(uint active_gc_threads) { |
97 void G1GCPhaseTimes::note_gc_start(uint active_gc_threads) { |
137 assert(active_gc_threads > 0, "The number of threads must be > 0"); |
98 assert(active_gc_threads > 0, "The number of threads must be > 0"); |
138 assert(active_gc_threads <= _max_gc_threads, "The number of active threads must be <= the max number of threads"); |
99 assert(active_gc_threads <= _max_gc_threads, "The number of active threads must be <= the max number of threads"); |
224 // return the average time for a phase in milliseconds |
151 // return the average time for a phase in milliseconds |
225 double G1GCPhaseTimes::average_time_ms(GCParPhases phase) { |
152 double G1GCPhaseTimes::average_time_ms(GCParPhases phase) { |
226 return _gc_par_phases[phase]->average(_active_gc_threads) * 1000.0; |
153 return _gc_par_phases[phase]->average(_active_gc_threads) * 1000.0; |
227 } |
154 } |
228 |
155 |
229 double G1GCPhaseTimes::get_time_ms(GCParPhases phase, uint worker_i) { |
|
230 return _gc_par_phases[phase]->get(worker_i) * 1000.0; |
|
231 } |
|
232 |
|
233 double G1GCPhaseTimes::sum_time_ms(GCParPhases phase) { |
|
234 return _gc_par_phases[phase]->sum(_active_gc_threads) * 1000.0; |
|
235 } |
|
236 |
|
237 double G1GCPhaseTimes::min_time_ms(GCParPhases phase) { |
|
238 return _gc_par_phases[phase]->minimum(_active_gc_threads) * 1000.0; |
|
239 } |
|
240 |
|
241 double G1GCPhaseTimes::max_time_ms(GCParPhases phase) { |
|
242 return _gc_par_phases[phase]->maximum(_active_gc_threads) * 1000.0; |
|
243 } |
|
244 |
|
245 size_t G1GCPhaseTimes::get_thread_work_item(GCParPhases phase, uint worker_i) { |
|
246 assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); |
|
247 return _gc_par_phases[phase]->thread_work_items()->get(worker_i); |
|
248 } |
|
249 |
|
250 size_t G1GCPhaseTimes::sum_thread_work_items(GCParPhases phase) { |
156 size_t G1GCPhaseTimes::sum_thread_work_items(GCParPhases phase) { |
251 assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); |
157 assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); |
252 return _gc_par_phases[phase]->thread_work_items()->sum(_active_gc_threads); |
158 return _gc_par_phases[phase]->thread_work_items()->sum(_active_gc_threads); |
253 } |
159 } |
254 |
160 |
255 double G1GCPhaseTimes::average_thread_work_items(GCParPhases phase) { |
161 template <class T> |
256 assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); |
162 void G1GCPhaseTimes::details(T* phase, const char* indent) { |
257 return _gc_par_phases[phase]->thread_work_items()->average(_active_gc_threads); |
163 LogHandle(gc, phases, task) log; |
258 } |
164 if (log.is_level(LogLevel::Trace)) { |
259 |
165 outputStream* trace_out = log.trace_stream(); |
260 size_t G1GCPhaseTimes::min_thread_work_items(GCParPhases phase) { |
166 trace_out->print("%s", indent); |
261 assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); |
167 phase->print_details_on(trace_out, _active_gc_threads); |
262 return _gc_par_phases[phase]->thread_work_items()->minimum(_active_gc_threads); |
168 } |
263 } |
169 } |
264 |
170 |
265 size_t G1GCPhaseTimes::max_thread_work_items(GCParPhases phase) { |
171 void G1GCPhaseTimes::log_phase(WorkerDataArray<double>* phase, uint indent, outputStream* out, bool print_sum) { |
266 assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); |
172 out->print("%s", Indents[indent]); |
267 return _gc_par_phases[phase]->thread_work_items()->maximum(_active_gc_threads); |
173 phase->print_summary_on(out, _active_gc_threads, print_sum); |
268 } |
174 details(phase, Indents[indent]); |
269 |
175 |
270 class G1GCParPhasePrinter : public StackObj { |
176 WorkerDataArray<size_t>* work_items = phase->thread_work_items(); |
271 G1GCPhaseTimes* _phase_times; |
177 if (work_items != NULL) { |
272 public: |
178 out->print("%s", Indents[indent + 1]); |
273 G1GCParPhasePrinter(G1GCPhaseTimes* phase_times) : _phase_times(phase_times) {} |
179 work_items->print_summary_on(out, _active_gc_threads, true); |
274 |
180 details(work_items, Indents[indent + 1]); |
275 void print(G1GCPhaseTimes::GCParPhases phase_id) { |
181 } |
276 WorkerDataArray<double>* phase = _phase_times->_gc_par_phases[phase_id]; |
182 } |
277 |
183 |
278 if (phase->_length == 1) { |
184 void G1GCPhaseTimes::debug_phase(WorkerDataArray<double>* phase) { |
279 print_single_length(phase_id, phase); |
185 LogHandle(gc, phases) log; |
280 } else { |
186 if (log.is_level(LogLevel::Debug)) { |
281 print_multi_length(phase_id, phase); |
187 ResourceMark rm; |
282 } |
188 log_phase(phase, 2, log.debug_stream(), true); |
283 } |
189 } |
284 |
190 } |
285 |
191 |
286 private: |
192 void G1GCPhaseTimes::trace_phase(WorkerDataArray<double>* phase, bool print_sum) { |
287 void print_single_length(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray<double>* phase) { |
193 LogHandle(gc, phases) log; |
288 // No need for min, max, average and sum for only one worker |
194 if (log.is_level(LogLevel::Trace)) { |
289 log_debug(gc, phases)("%s%s: %.1lf", Indents[phase->_indent_level], phase->_title, _phase_times->get_time_ms(phase_id, 0)); |
195 ResourceMark rm; |
290 |
196 log_phase(phase, 3, log.trace_stream(), print_sum); |
291 WorkerDataArray<size_t>* work_items = phase->_thread_work_items; |
197 } |
292 if (work_items != NULL) { |
198 } |
293 log_debug(gc, phases)("%s%s: " SIZE_FORMAT, Indents[work_items->_indent_level], work_items->_title, _phase_times->sum_thread_work_items(phase_id)); |
199 |
294 } |
200 #define PHASE_DOUBLE_FORMAT "%s%s: %.1lfms" |
295 } |
201 #define PHASE_SIZE_FORMAT "%s%s: " SIZE_FORMAT |
296 |
202 |
297 void print_time_values(const char* indent, G1GCPhaseTimes::GCParPhases phase_id) { |
203 #define info_line(str, value) \ |
298 if (log_is_enabled(Trace, gc)) { |
204 log_info(gc, phases)(PHASE_DOUBLE_FORMAT, Indents[1], str, value); |
299 LineBuffer buf(0); |
205 |
300 uint active_length = _phase_times->_active_gc_threads; |
206 #define debug_line(str, value) \ |
301 for (uint i = 0; i < active_length; ++i) { |
207 log_debug(gc, phases)(PHASE_DOUBLE_FORMAT, Indents[2], str, value); |
302 buf.append(" %4.1lf", _phase_times->get_time_ms(phase_id, i)); |
208 |
303 } |
209 #define trace_line(str, value) \ |
304 const char* line = buf.to_string(); |
210 log_trace(gc, phases)(PHASE_DOUBLE_FORMAT, Indents[3], str, value); |
305 log_trace(gc, phases)("%s%-25s%s", indent, "", line); |
211 |
306 } |
212 #define trace_line_sz(str, value) \ |
307 } |
213 log_trace(gc, phases)(PHASE_SIZE_FORMAT, Indents[3], str, value); |
308 |
214 |
309 void print_count_values(const char* indent, G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray<size_t>* thread_work_items) { |
215 #define trace_line_ms(str, value) \ |
310 if (log_is_enabled(Trace, gc)) { |
216 log_trace(gc, phases)(PHASE_SIZE_FORMAT, Indents[3], str, value); |
311 LineBuffer buf(0); |
217 |
312 uint active_length = _phase_times->_active_gc_threads; |
218 #define info_line_and_account(str, value) \ |
313 for (uint i = 0; i < active_length; ++i) { |
219 info_line(str, value); \ |
314 buf.append(" " SIZE_FORMAT, _phase_times->get_thread_work_item(phase_id, i)); |
220 accounted_time_ms += value; |
315 } |
|
316 const char* line = buf.to_string(); |
|
317 log_trace(gc, phases)("%s%-25s%s", indent, "", line); |
|
318 } |
|
319 } |
|
320 |
|
321 void print_thread_work_items(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray<size_t>* thread_work_items) { |
|
322 const char* indent = Indents[thread_work_items->_indent_level]; |
|
323 |
|
324 assert(thread_work_items->_print_sum, "%s does not have print sum true even though it is a count", thread_work_items->_title); |
|
325 |
|
326 log_debug(gc, phases)("%s%-25s Min: " SIZE_FORMAT ", Avg: %4.1lf, Max: " SIZE_FORMAT ", Diff: " SIZE_FORMAT ", Sum: " SIZE_FORMAT, |
|
327 indent, thread_work_items->_title, |
|
328 _phase_times->min_thread_work_items(phase_id), _phase_times->average_thread_work_items(phase_id), _phase_times->max_thread_work_items(phase_id), |
|
329 _phase_times->max_thread_work_items(phase_id) - _phase_times->min_thread_work_items(phase_id), _phase_times->sum_thread_work_items(phase_id)); |
|
330 |
|
331 print_count_values(indent, phase_id, thread_work_items); |
|
332 } |
|
333 |
|
334 void print_multi_length(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray<double>* phase) { |
|
335 const char* indent = Indents[phase->_indent_level]; |
|
336 |
|
337 if (phase->_print_sum) { |
|
338 log_debug(gc, phases)("%s%-25s Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf, Sum: %4.1lf", |
|
339 indent, phase->_title, |
|
340 _phase_times->min_time_ms(phase_id), _phase_times->average_time_ms(phase_id), _phase_times->max_time_ms(phase_id), |
|
341 _phase_times->max_time_ms(phase_id) - _phase_times->min_time_ms(phase_id), _phase_times->sum_time_ms(phase_id)); |
|
342 } else { |
|
343 log_debug(gc, phases)("%s%-25s Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf", |
|
344 indent, phase->_title, |
|
345 _phase_times->min_time_ms(phase_id), _phase_times->average_time_ms(phase_id), _phase_times->max_time_ms(phase_id), |
|
346 _phase_times->max_time_ms(phase_id) - _phase_times->min_time_ms(phase_id)); |
|
347 } |
|
348 |
|
349 print_time_values(indent, phase_id); |
|
350 |
|
351 if (phase->_thread_work_items != NULL) { |
|
352 print_thread_work_items(phase_id, phase->_thread_work_items); |
|
353 } |
|
354 } |
|
355 }; |
|
356 |
221 |
357 void G1GCPhaseTimes::print() { |
222 void G1GCPhaseTimes::print() { |
358 note_gc_end(); |
223 note_gc_end(); |
359 |
224 |
360 G1GCParPhasePrinter par_phase_printer(this); |
225 double accounted_time_ms = _external_accounted_time_ms; |
361 |
|
362 if (_root_region_scan_wait_time_ms > 0.0) { |
226 if (_root_region_scan_wait_time_ms > 0.0) { |
363 print_stats(Indents[1], "Root Region Scan Waiting", _root_region_scan_wait_time_ms); |
227 info_line_and_account("Root Region Scan Waiting", _root_region_scan_wait_time_ms); |
364 } |
228 } |
365 |
229 |
366 print_stats(Indents[1], "Parallel Time", _cur_collection_par_time_ms); |
230 info_line_and_account("Evacuate Collection Set", _cur_collection_par_time_ms); |
367 for (int i = 0; i <= GCMainParPhasesLast; i++) { |
231 trace_phase(_gc_par_phases[GCWorkerStart], false); |
368 par_phase_printer.print((GCParPhases) i); |
232 debug_phase(_gc_par_phases[ExtRootScan]); |
369 } |
233 for (int i = ThreadRoots; i <= SATBFiltering; i++) { |
370 |
234 trace_phase(_gc_par_phases[i]); |
371 print_stats(Indents[1], "Code Root Fixup", _cur_collection_code_root_fixup_time_ms); |
235 } |
372 print_stats(Indents[1], "Code Root Purge", _cur_strong_code_root_purge_time_ms); |
236 debug_phase(_gc_par_phases[UpdateRS]); |
|
237 if (ConcurrentG1Refine::hot_card_cache_enabled()) { |
|
238 trace_phase(_gc_par_phases[ScanHCC]); |
|
239 } |
|
240 debug_phase(_gc_par_phases[ScanRS]); |
|
241 debug_phase(_gc_par_phases[CodeRoots]); |
|
242 debug_phase(_gc_par_phases[ObjCopy]); |
|
243 debug_phase(_gc_par_phases[Termination]); |
|
244 debug_phase(_gc_par_phases[Other]); |
|
245 debug_phase(_gc_par_phases[GCWorkerTotal]); |
|
246 trace_phase(_gc_par_phases[GCWorkerEnd], false); |
|
247 |
|
248 info_line_and_account("Code Roots", _cur_collection_code_root_fixup_time_ms + _cur_strong_code_root_purge_time_ms); |
|
249 debug_line("Code Roots Fixup", _cur_collection_code_root_fixup_time_ms); |
|
250 debug_line("Code Roots Purge", _cur_strong_code_root_purge_time_ms); |
|
251 |
373 if (G1StringDedup::is_enabled()) { |
252 if (G1StringDedup::is_enabled()) { |
374 print_stats(Indents[1], "String Dedup Fixup", _cur_string_dedup_fixup_time_ms); |
253 info_line_and_account("String Dedup Fixup", _cur_string_dedup_fixup_time_ms); |
375 for (int i = StringDedupPhasesFirst; i <= StringDedupPhasesLast; i++) { |
254 debug_phase(_gc_par_phases[StringDedupQueueFixup]); |
376 par_phase_printer.print((GCParPhases) i); |
255 debug_phase(_gc_par_phases[StringDedupTableFixup]); |
377 } |
256 } |
378 } |
257 info_line_and_account("Clear Card Table", _cur_clear_ct_time_ms); |
379 print_stats(Indents[1], "Clear CT", _cur_clear_ct_time_ms); |
258 info_line_and_account("Expand Heap After Collection", _cur_expand_heap_time_ms); |
380 print_stats(Indents[1], "Expand Heap After Collection", _cur_expand_heap_time_ms); |
259 |
381 double misc_time_ms = _gc_pause_time_ms - accounted_time_ms(); |
260 double free_cset_time = _recorded_young_free_cset_time_ms + _recorded_non_young_free_cset_time_ms; |
382 print_stats(Indents[1], "Other", misc_time_ms); |
261 info_line_and_account("Free Collection Set", free_cset_time); |
|
262 debug_line("Young Free Collection Set", _recorded_young_free_cset_time_ms); |
|
263 debug_line("Non-Young Free Collection Set", _recorded_non_young_free_cset_time_ms); |
|
264 info_line_and_account("Merge Per-Thread State", _recorded_merge_pss_time_ms); |
|
265 |
|
266 info_line("Other", _gc_pause_time_ms - accounted_time_ms); |
383 if (_cur_verify_before_time_ms > 0.0) { |
267 if (_cur_verify_before_time_ms > 0.0) { |
384 print_stats(Indents[2], "Verify Before", _cur_verify_before_time_ms); |
268 debug_line("Verify Before", _cur_verify_before_time_ms); |
385 } |
269 } |
386 if (G1CollectedHeap::heap()->evacuation_failed()) { |
270 if (G1CollectedHeap::heap()->evacuation_failed()) { |
387 double evac_fail_handling = _cur_evac_fail_recalc_used + _cur_evac_fail_remove_self_forwards + |
271 double evac_fail_handling = _cur_evac_fail_recalc_used + _cur_evac_fail_remove_self_forwards + |
388 _cur_evac_fail_restore_remsets; |
272 _cur_evac_fail_restore_remsets; |
389 print_stats(Indents[2], "Evacuation Failure", evac_fail_handling); |
273 debug_line("Evacuation Failure", evac_fail_handling); |
390 log_trace(gc, phases)("%sRecalculate Used: %.1lf ms", Indents[3], _cur_evac_fail_recalc_used); |
274 trace_line("Recalculate Used", _cur_evac_fail_recalc_used); |
391 log_trace(gc, phases)("%sRemove Self Forwards: %.1lf ms", Indents[3], _cur_evac_fail_remove_self_forwards); |
275 trace_line("Remove Self Forwards",_cur_evac_fail_remove_self_forwards); |
392 log_trace(gc, phases)("%sRestore RemSet: %.1lf ms", Indents[3], _cur_evac_fail_restore_remsets); |
276 trace_line("Restore RemSet", _cur_evac_fail_restore_remsets); |
393 } |
277 } |
394 print_stats(Indents[2], "Choose CSet", |
278 debug_line("Choose CSet", (_recorded_young_cset_choice_time_ms + _recorded_non_young_cset_choice_time_ms)); |
395 (_recorded_young_cset_choice_time_ms + |
279 debug_line("Preserve CM Refs", _recorded_preserve_cm_referents_time_ms); |
396 _recorded_non_young_cset_choice_time_ms)); |
280 debug_line("Ref Proc", _cur_ref_proc_time_ms); |
397 print_stats(Indents[2], "Preserve CM Refs", _recorded_preserve_cm_referents_time_ms); |
281 debug_line("Ref Enq", _cur_ref_enq_time_ms); |
398 print_stats(Indents[2], "Ref Proc", _cur_ref_proc_time_ms); |
282 debug_line("Redirty Cards", _recorded_redirty_logged_cards_time_ms); |
399 print_stats(Indents[2], "Ref Enq", _cur_ref_enq_time_ms); |
283 trace_phase(_gc_par_phases[RedirtyCards]); |
400 print_stats(Indents[2], "Redirty Cards", _recorded_redirty_logged_cards_time_ms); |
284 trace_phase(_gc_par_phases[PreserveCMReferents]); |
401 par_phase_printer.print(RedirtyCards); |
|
402 par_phase_printer.print(PreserveCMReferents); |
|
403 if (G1EagerReclaimHumongousObjects) { |
285 if (G1EagerReclaimHumongousObjects) { |
404 print_stats(Indents[2], "Humongous Register", _cur_fast_reclaim_humongous_register_time_ms); |
286 debug_line("Humongous Register", _cur_fast_reclaim_humongous_register_time_ms); |
405 |
287 trace_line_sz("Humongous Total", _cur_fast_reclaim_humongous_total); |
406 log_trace(gc, phases)("%sHumongous Total: " SIZE_FORMAT, Indents[3], _cur_fast_reclaim_humongous_total); |
288 trace_line_sz("Humongous Candidate", _cur_fast_reclaim_humongous_candidates); |
407 log_trace(gc, phases)("%sHumongous Candidate: " SIZE_FORMAT, Indents[3], _cur_fast_reclaim_humongous_candidates); |
289 debug_line("Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms); |
408 print_stats(Indents[2], "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms); |
290 trace_line_sz("Humongous Reclaimed", _cur_fast_reclaim_humongous_reclaimed); |
409 log_trace(gc, phases)("%sHumongous Reclaimed: " SIZE_FORMAT, Indents[3], _cur_fast_reclaim_humongous_reclaimed); |
291 } |
410 } |
|
411 print_stats(Indents[2], "Free CSet", |
|
412 (_recorded_young_free_cset_time_ms + |
|
413 _recorded_non_young_free_cset_time_ms)); |
|
414 log_trace(gc, phases)("%sYoung Free CSet: %.1lf ms", Indents[3], _recorded_young_free_cset_time_ms); |
|
415 log_trace(gc, phases)("%sNon-Young Free CSet: %.1lf ms", Indents[3], _recorded_non_young_free_cset_time_ms); |
|
416 print_stats(Indents[2], "Merge Per-Thread State", _recorded_merge_pss_time_ms); |
|
417 if (_cur_verify_after_time_ms > 0.0) { |
292 if (_cur_verify_after_time_ms > 0.0) { |
418 print_stats(Indents[2], "Verify After", _cur_verify_after_time_ms); |
293 debug_line("Verify After", _cur_verify_after_time_ms); |
419 } |
294 } |
420 } |
295 } |
421 |
296 |
422 G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id) : |
297 G1GCParPhaseTimesTracker::G1GCParPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCParPhases phase, uint worker_id) : |
423 _phase_times(phase_times), _phase(phase), _worker_id(worker_id) { |
298 _phase_times(phase_times), _phase(phase), _worker_id(worker_id) { |