src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hs-gc-g1-logging-remove-serial Cdiff src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp

src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp

Print this page
rev 3484 : 7178363: G1: Remove the serial code for PrintGCDetails and make it a special case of the parallel code
Summary: Introduced the WorkerDataArray class.
Reviewed-by: mgerdin

*** 77,107 **** gclog_or_tty->print_cr("%s", _buffer); _cur = _indent_level * INDENT_CHARS; } }; G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : _max_gc_threads(max_gc_threads), _min_clear_cc_time_ms(-1.0), _max_clear_cc_time_ms(-1.0), _cur_clear_cc_time_ms(0.0), _cum_clear_cc_time_ms(0.0), ! _num_cc_clears(0L) { assert(max_gc_threads > 0, "Must have some GC threads"); - _par_last_gc_worker_start_times_ms = new double[_max_gc_threads]; - _par_last_ext_root_scan_times_ms = new double[_max_gc_threads]; - _par_last_satb_filtering_times_ms = new double[_max_gc_threads]; - _par_last_update_rs_times_ms = new double[_max_gc_threads]; - _par_last_update_rs_processed_buffers = new double[_max_gc_threads]; - _par_last_scan_rs_times_ms = new double[_max_gc_threads]; - _par_last_obj_copy_times_ms = new double[_max_gc_threads]; - _par_last_termination_times_ms = new double[_max_gc_threads]; - _par_last_termination_attempts = new double[_max_gc_threads]; - _par_last_gc_worker_end_times_ms = new double[_max_gc_threads]; - _par_last_gc_worker_times_ms = new double[_max_gc_threads]; - _par_last_gc_worker_other_times_ms = new double[_max_gc_threads]; } void G1GCPhaseTimes::note_gc_start(double pause_start_time_sec, uint active_gc_threads, bool is_young_gc, bool is_initial_mark_gc, GCCause::Cause gc_cause) { assert(active_gc_threads > 0, "The number of threads must be > 0"); --- 77,175 ---- gclog_or_tty->print_cr("%s", _buffer); _cur = _indent_level * INDENT_CHARS; } }; + template <class T> + void WorkerDataArray<T>::print(int level, const char* title) { + if (_length == 1) { + // No need for min, max, average and sum for only one worker + LineBuffer buf(level); + buf.append("[%s: ", title); + buf.append(_print_format, _data[0]); + buf.append_and_print_cr("]"); + return; + } + + T min = _data[0]; + T max = _data[0]; + T sum = 0; + + LineBuffer buf(level); + buf.append("[%s:", title); + for (uint i = 0; i < _length; ++i) { + T val = _data[i]; + min = MIN2(val, min); + max = MAX2(val, max); + sum += val; + if (G1Log::finest()) { + buf.append(" "); + buf.append(_print_format, val); + } + } + + if (G1Log::finest()) { + buf.append_and_print_cr(""); + } + + double avg = (double)sum / (double)_length; + buf.append(" Min: "); + buf.append(_print_format, min); + buf.append(", Avg: "); + buf.append("%.1lf", avg); // Always print average as a double + buf.append(", Max: "); + buf.append(_print_format, max); + buf.append(", Diff: "); + buf.append(_print_format, max - min); + if (_print_sum) { + // for things like the start and end times the sum is not + // that relevant + buf.append(", Sum: "); + buf.append(_print_format, sum); + } + buf.append_and_print_cr("]"); + } + + #ifdef ASSERT + + template <class T> + void WorkerDataArray<T>::reset() { + for (uint i = 0; i < _length; i++) { + _data[i] = (T)-1; + } + } + + template <class T> + void WorkerDataArray<T>::verify() { + for (uint i = 0; i < _length; i++) { + assert(_data[i] >= (T)0, err_msg("Invalid data for worker %d", i)); + } + } + + #endif + G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : _max_gc_threads(max_gc_threads), _min_clear_cc_time_ms(-1.0), _max_clear_cc_time_ms(-1.0), _cur_clear_cc_time_ms(0.0), _cum_clear_cc_time_ms(0.0), ! _num_cc_clears(0L), ! _last_gc_worker_start_times_ms(_max_gc_threads, "%.1lf", false), ! _last_ext_root_scan_times_ms(_max_gc_threads, "%.1lf"), ! _last_satb_filtering_times_ms(_max_gc_threads, "%.1lf"), ! _last_update_rs_times_ms(_max_gc_threads, "%.1lf"), ! _last_update_rs_processed_buffers(_max_gc_threads, "%d"), ! _last_scan_rs_times_ms(_max_gc_threads, "%.1lf"), ! _last_obj_copy_times_ms(_max_gc_threads, "%.1lf"), ! _last_termination_times_ms(_max_gc_threads, "%.1lf"), ! _last_termination_attempts(_max_gc_threads, SIZE_FORMAT), ! _last_gc_worker_end_times_ms(_max_gc_threads, "%.1lf", false), ! _last_gc_worker_times_ms(_max_gc_threads, "%.1lf"), ! _last_gc_worker_other_times_ms(_max_gc_threads, "%.1lf") { assert(max_gc_threads > 0, "Must have some GC threads"); } void G1GCPhaseTimes::note_gc_start(double pause_start_time_sec, uint active_gc_threads, bool is_young_gc, bool is_initial_mark_gc, GCCause::Cause gc_cause) { assert(active_gc_threads > 0, "The number of threads must be > 0");
*** 110,276 **** _pause_start_time_sec = pause_start_time_sec; _is_young_gc = is_young_gc; _is_initial_mark_gc = is_initial_mark_gc; _gc_cause = gc_cause; ! #ifdef ASSERT ! // initialise the timing data to something well known so that we can spot ! // if something is not set properly ! ! for (uint i = 0; i < _max_gc_threads; ++i) { ! _par_last_gc_worker_start_times_ms[i] = -1234.0; ! _par_last_ext_root_scan_times_ms[i] = -1234.0; ! _par_last_satb_filtering_times_ms[i] = -1234.0; ! _par_last_update_rs_times_ms[i] = -1234.0; ! _par_last_update_rs_processed_buffers[i] = -1234.0; ! _par_last_scan_rs_times_ms[i] = -1234.0; ! _par_last_obj_copy_times_ms[i] = -1234.0; ! _par_last_termination_times_ms[i] = -1234.0; ! _par_last_termination_attempts[i] = -1234.0; ! _par_last_gc_worker_end_times_ms[i] = -1234.0; ! _par_last_gc_worker_times_ms[i] = -1234.0; ! _par_last_gc_worker_other_times_ms[i] = -1234.0; ! } ! #endif } void G1GCPhaseTimes::note_gc_end(double pause_end_time_sec) { if (G1Log::fine()) { double pause_time_ms = (pause_end_time_sec - _pause_start_time_sec) * MILLIUNITS; for (uint i = 0; i < _active_gc_threads; i++) { ! _par_last_gc_worker_times_ms[i] = _par_last_gc_worker_end_times_ms[i] - ! _par_last_gc_worker_start_times_ms[i]; ! double worker_known_time = _par_last_ext_root_scan_times_ms[i] + ! _par_last_satb_filtering_times_ms[i] + ! _par_last_update_rs_times_ms[i] + ! _par_last_scan_rs_times_ms[i] + ! _par_last_obj_copy_times_ms[i] + ! _par_last_termination_times_ms[i]; ! _par_last_gc_worker_other_times_ms[i] = _par_last_gc_worker_times_ms[i] - ! worker_known_time; } ! print(pause_time_ms); ! } ! } ! ! void G1GCPhaseTimes::print_par_stats(int level, ! const char* str, ! double* data, ! bool showDecimals) { ! double min = data[0], max = data[0]; ! double total = 0.0; ! LineBuffer buf(level); ! buf.append("[%s (ms):", str); ! for (uint i = 0; i < _active_gc_threads; ++i) { ! double val = data[i]; ! if (val < min) ! min = val; ! if (val > max) ! max = val; ! total += val; ! if (G1Log::finest()) { ! if (showDecimals) { ! buf.append(" %.1lf", val); ! } else { ! buf.append(" %d", (int)val); ! } ! } } - if (G1Log::finest()) { - buf.append_and_print_cr(""); - } - double avg = total / (double) _active_gc_threads; - if (showDecimals) { - buf.append_and_print_cr(" Min: %.1lf, Avg: %.1lf, Max: %.1lf, Diff: %.1lf, Sum: %.1lf]", - min, avg, max, max - min, total); - } else { - buf.append_and_print_cr(" Min: %d, Avg: %d, Max: %d, Diff: %d, Sum: %d]", - (int)min, (int)avg, (int)max, (int)max - (int)min, (int)total); - } } void G1GCPhaseTimes::print_stats(int level, const char* str, double value) { LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value); } void G1GCPhaseTimes::print_stats(int level, const char* str, double value, int workers) { LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %d]", str, value, workers); } - void G1GCPhaseTimes::print_stats(int level, const char* str, int value) { - LineBuffer(level).append_and_print_cr("[%s: %d]", str, value); - } - - double G1GCPhaseTimes::avg_value(double* data) { - if (G1CollectedHeap::use_parallel_gc_threads()) { - double ret = 0.0; - for (uint i = 0; i < _active_gc_threads; ++i) { - ret += data[i]; - } - return ret / (double) _active_gc_threads; - } else { - return data[0]; - } - } - - double G1GCPhaseTimes::max_value(double* data) { - if (G1CollectedHeap::use_parallel_gc_threads()) { - double ret = data[0]; - for (uint i = 1; i < _active_gc_threads; ++i) { - if (data[i] > ret) { - ret = data[i]; - } - } - return ret; - } else { - return data[0]; - } - } - - double G1GCPhaseTimes::sum_of_values(double* data) { - if (G1CollectedHeap::use_parallel_gc_threads()) { - double sum = 0.0; - for (uint i = 0; i < _active_gc_threads; i++) { - sum += data[i]; - } - return sum; - } else { - return data[0]; - } - } - - double G1GCPhaseTimes::max_sum(double* data1, double* data2) { - double ret = data1[0] + data2[0]; - - if (G1CollectedHeap::use_parallel_gc_threads()) { - for (uint i = 1; i < _active_gc_threads; ++i) { - double data = data1[i] + data2[i]; - if (data > ret) { - ret = data; - } - } - } - return ret; - } - - void G1GCPhaseTimes::collapse_par_times() { - _ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms); - _satb_filtering_time = avg_value(_par_last_satb_filtering_times_ms); - _update_rs_time = avg_value(_par_last_update_rs_times_ms); - _update_rs_processed_buffers = - sum_of_values(_par_last_update_rs_processed_buffers); - _scan_rs_time = avg_value(_par_last_scan_rs_times_ms); - _obj_copy_time = avg_value(_par_last_obj_copy_times_ms); - _termination_time = avg_value(_par_last_termination_times_ms); - } - double G1GCPhaseTimes::accounted_time_ms() { // Subtract the root region scanning wait time. It's initialized to // zero at the start of the pause. double misc_time_ms = _root_region_scan_wait_time_ms; --- 178,247 ---- _pause_start_time_sec = pause_start_time_sec; _is_young_gc = is_young_gc; _is_initial_mark_gc = is_initial_mark_gc; _gc_cause = gc_cause; ! _last_gc_worker_start_times_ms.reset(); ! _last_ext_root_scan_times_ms.reset(); ! _last_satb_filtering_times_ms.reset(); ! _last_update_rs_times_ms.reset(); ! _last_update_rs_processed_buffers.reset(); ! _last_scan_rs_times_ms.reset(); ! _last_obj_copy_times_ms.reset(); ! _last_termination_times_ms.reset(); ! _last_termination_attempts.reset(); ! _last_gc_worker_end_times_ms.reset(); ! _last_gc_worker_times_ms.reset(); ! _last_gc_worker_other_times_ms.reset(); } void G1GCPhaseTimes::note_gc_end(double pause_end_time_sec) { + _last_gc_worker_start_times_ms.verify(); + _last_ext_root_scan_times_ms.verify(); + _last_satb_filtering_times_ms.verify(); + _last_update_rs_times_ms.verify(); + _last_update_rs_processed_buffers.verify(); + _last_scan_rs_times_ms.verify(); + _last_obj_copy_times_ms.verify(); + _last_termination_times_ms.verify(); + _last_termination_attempts.verify(); + _last_gc_worker_end_times_ms.verify(); + if (G1Log::fine()) { double pause_time_ms = (pause_end_time_sec - _pause_start_time_sec) * MILLIUNITS; for (uint i = 0; i < _active_gc_threads; i++) { ! _last_gc_worker_times_ms.set(i, ! _last_gc_worker_end_times_ms.get(i) - _last_gc_worker_start_times_ms.get(i)); ! double worker_known_time = _last_ext_root_scan_times_ms.get(i) + ! _last_satb_filtering_times_ms.get(i) + ! _last_update_rs_times_ms.get(i) + ! _last_scan_rs_times_ms.get(i) + ! _last_obj_copy_times_ms.get(i) + ! _last_termination_times_ms.get(i); ! _last_gc_worker_other_times_ms.set(i, ! _last_gc_worker_times_ms.get(i) - worker_known_time); } ! _last_gc_worker_times_ms.verify(); ! _last_gc_worker_other_times_ms.verify(); ! print(pause_time_ms); } } void G1GCPhaseTimes::print_stats(int level, const char* str, double value) { LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value); } void G1GCPhaseTimes::print_stats(int level, const char* str, double value, int workers) { LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %d]", str, value, workers); } double G1GCPhaseTimes::accounted_time_ms() { // Subtract the root region scanning wait time. It's initialized to // zero at the start of the pause. double misc_time_ms = _root_region_scan_wait_time_ms;
*** 305,345 **** if (_root_region_scan_wait_time_ms > 0.0) { print_stats(1, "Root Region Scan Waiting", _root_region_scan_wait_time_ms); } if (G1CollectedHeap::use_parallel_gc_threads()) { print_stats(1, "Parallel Time", _cur_collection_par_time_ms, _active_gc_threads); ! print_par_stats(2, "GC Worker Start", _par_last_gc_worker_start_times_ms); ! print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms); ! if (_satb_filtering_time > 0.0) { ! print_par_stats(2, "SATB Filtering", _par_last_satb_filtering_times_ms); } ! print_par_stats(2, "Update RS", _par_last_update_rs_times_ms); if (G1Log::finest()) { ! print_par_stats(3, "Processed Buffers", _par_last_update_rs_processed_buffers, ! false /* showDecimals */); } ! print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms); ! print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms); ! print_par_stats(2, "Termination", _par_last_termination_times_ms); if (G1Log::finest()) { ! print_par_stats(3, "Termination Attempts", _par_last_termination_attempts, ! false /* showDecimals */); } ! print_par_stats(2, "GC Worker Other", _par_last_gc_worker_other_times_ms); ! print_par_stats(2, "GC Worker Total", _par_last_gc_worker_times_ms); ! print_par_stats(2, "GC Worker End", _par_last_gc_worker_end_times_ms); } else { ! print_stats(1, "Ext Root Scanning", _ext_root_scan_time); ! if (_satb_filtering_time > 0.0) { ! print_stats(1, "SATB Filtering", _satb_filtering_time); } ! print_stats(1, "Update RS", _update_rs_time); if (G1Log::finest()) { ! print_stats(2, "Processed Buffers", (int)_update_rs_processed_buffers); } ! print_stats(1, "Scan RS", _scan_rs_time); ! print_stats(1, "Object Copying", _obj_copy_time); } print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms); print_stats(1, "Clear CT", _cur_clear_ct_time_ms); if (Verbose && G1Log::finest()) { print_stats(1, "Cur Clear CC", _cur_clear_cc_time_ms); --- 276,314 ---- if (_root_region_scan_wait_time_ms > 0.0) { print_stats(1, "Root Region Scan Waiting", _root_region_scan_wait_time_ms); } if (G1CollectedHeap::use_parallel_gc_threads()) { print_stats(1, "Parallel Time", _cur_collection_par_time_ms, _active_gc_threads); ! _last_gc_worker_start_times_ms.print(2, "GC Worker Start (ms)"); ! _last_ext_root_scan_times_ms.print(2, "Ext Root Scanning (ms)"); ! if (_last_satb_filtering_times_ms.sum() > 0.0) { ! _last_satb_filtering_times_ms.print(2, "SATB Filtering (ms)"); } ! _last_update_rs_times_ms.print(2, "Update RS (ms)"); if (G1Log::finest()) { ! _last_update_rs_processed_buffers.print(3, "Processed Buffers"); } ! _last_scan_rs_times_ms.print(2, "Scan RS (ms)"); ! _last_obj_copy_times_ms.print(2, "Object Copy (ms)"); ! _last_termination_times_ms.print(2, "Termination (ms)"); if (G1Log::finest()) { ! _last_termination_attempts.print(3, "Termination Attempts"); } ! _last_gc_worker_other_times_ms.print(2, "GC Worker Other (ms)"); ! _last_gc_worker_times_ms.print(2, "GC Worker Total (ms)"); ! _last_gc_worker_end_times_ms.print(2, "GC Worker End (ms)"); } else { ! _last_ext_root_scan_times_ms.print(1, "Ext Root Scanning (ms)"); ! if (_last_satb_filtering_times_ms.sum() > 0.0) { ! _last_satb_filtering_times_ms.print(1, "SATB Filtering (ms)"); } ! _last_update_rs_times_ms.print(1, "Update RS (ms)"); if (G1Log::finest()) { ! _last_update_rs_processed_buffers.print(2, "Processed Buffers"); } ! _last_scan_rs_times_ms.print(1, "Scan RS (ms)"); ! _last_obj_copy_times_ms.print(1, "Object Copy (ms)"); } print_stats(1, "Code Root Fixup", _cur_collection_code_root_fixup_time_ms); print_stats(1, "Clear CT", _cur_clear_ct_time_ms); if (Verbose && G1Log::finest()) { print_stats(1, "Cur Clear CC", _cur_clear_cc_time_ms);
src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File