--- old/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp 2015-03-02 17:11:33.635356472 +0100 +++ new/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp 2015-03-02 17:11:33.535356476 +0100 @@ -31,6 +31,7 @@ template class WorkerDataArray : public CHeapObj { + friend class G1GCPhasePrinter; T* _data; uint _length; const char* _title; @@ -49,10 +50,10 @@ // without having to worry about the cost. bool _has_new_data; T _sum; + T _min; + T _max; double _average; - void log_value(LineBuffer& buf, T value); - public: WorkerDataArray(uint length, const char* title, bool print_sum, int log_level, uint indent_level); @@ -62,6 +63,8 @@ _sub_count = sub_count; } + WorkerDataArray* sub_count() { return _sub_count; } + void set(uint worker_i, T value) { assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length)); assert(_data[worker_i] == WorkerDataArray::uninitialized(), err_msg("Overwriting data for worker %d in %s", worker_i, _title)); @@ -74,11 +77,6 @@ _sub_count->set(worker_i, value); } - size_t sub_count_sum() { - assert(_sub_count != NULL, "No sub count"); - return _sub_count->sum(); - } - T get(uint worker_i) { assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length)); assert(_data[worker_i] != WorkerDataArray::uninitialized(), err_msg("No data to add to for worker %d", worker_i)); @@ -93,20 +91,24 @@ } double average(){ - if (_has_new_data) { - calculate_totals(); - } + calculate_totals(); return _average; } T sum() { - if (_has_new_data) { - calculate_totals(); - } + calculate_totals(); return _sum; } - void print(); + T minimum() { + calculate_totals(); + return _min; + } + + T maximum() { + calculate_totals(); + return _max; + } void reset() PRODUCT_RETURN; void verify() PRODUCT_RETURN; @@ -118,9 +120,18 @@ private: void calculate_totals(){ + if (!_has_new_data) { + return; + } + _sum = (T)0; + _min = _data[0]; + _max = _min; for (uint i = 0; i < _length; ++i) { - _sum += _data[i]; + T val = _data[i]; + _sum += val; + _min = MIN2(_min, val); + _max = MAX2(_max, val); } _average = (double)_sum / (double)_length; _has_new_data = false; @@ -128,6 +139,8 @@ }; class G1GCPhaseTimes : public CHeapObj { + friend class G1GCPhasePrinter; + uint _active_gc_threads; uint _max_gc_threads; @@ -206,26 +219,75 @@ void note_gc_end(); void print(double pause_time_sec); - void record_time(GCPhases phase, uint worker_i, double time) { - _gc_phases[phase]->set(worker_i, time); + // record the time a phase took in seconds + void record_time_secs(GCPhases phase, uint worker_i, double secs) { + _gc_phases[phase]->set(worker_i, secs); } - void add_time(GCPhases phase, uint worker_i, double time) { - _gc_phases[phase]->add(worker_i, time); + // add a number of seconds to a phase + void add_time_secs(GCPhases phase, uint worker_i, double secs) { + _gc_phases[phase]->add(worker_i, secs); } void record_sub_count(GCPhases phase, uint worker_i, size_t count) { _gc_phases[phase]->set_sub_count(worker_i, count); } - double average_time(GCPhases phase) { - return _gc_phases[phase]->average(); + // return the average time for a phase in milliseconds + double average_time_ms(GCPhases phase) { + return _gc_phases[phase]->average() * 1000.0; } size_t sub_count_sum(GCPhases phase) { - return _gc_phases[phase]->sub_count_sum(); + assert(_gc_phases[phase]->sub_count() != NULL, "No sub count"); + return _gc_phases[phase]->sub_count()->sum(); + } + + private: + + double get_time_ms(GCPhases phase, uint worker_i) { + return _gc_phases[phase]->get(worker_i) * 1000.0; } + double sum_time_ms(GCPhases phase) { + return _gc_phases[phase]->sum() * 1000.0; + } + + double min_time_ms(GCPhases phase) { + return _gc_phases[phase]->minimum() * 1000.0; + } + + double max_time_ms(GCPhases phase) { + return _gc_phases[phase]->maximum() * 1000.0; + } + + size_t get_sub_count(GCPhases phase, uint worker_i) { + assert(_gc_phases[phase]->sub_count() != NULL, "No sub count"); + return _gc_phases[phase]->sub_count()->get(worker_i); + } + + size_t sum_sub_count(GCPhases phase) { + assert(_gc_phases[phase]->sub_count() != NULL, "No sub count"); + return _gc_phases[phase]->sub_count()->sum(); + } + + double average_sub_count(GCPhases phase) { + assert(_gc_phases[phase]->sub_count() != NULL, "No sub count"); + return _gc_phases[phase]->sub_count()->average(); + } + + size_t min_sub_count(GCPhases phase) { + assert(_gc_phases[phase]->sub_count() != NULL, "No sub count"); + return _gc_phases[phase]->sub_count()->minimum(); + } + + size_t max_sub_count(GCPhases phase) { + assert(_gc_phases[phase]->sub_count() != NULL, "No sub count"); + return _gc_phases[phase]->sub_count()->maximum(); + } + + public: + void record_clear_ct_time(double ms) { _cur_clear_ct_time_ms = ms; } @@ -362,4 +424,16 @@ ~G1GCPhaseTimesTracker(); }; +class G1GCPhasePrinter : public StackObj { + G1GCPhaseTimes* _phase_times; + void print_single_length(G1GCPhaseTimes::GCPhases phase_id, WorkerDataArray* phase); + void print_multi_length(G1GCPhaseTimes::GCPhases phase_id, WorkerDataArray* phase); + void print_sub_count(G1GCPhaseTimes::GCPhases phase_id, WorkerDataArray* sub_count); + void print_time_values(LineBuffer& buf, G1GCPhaseTimes::GCPhases phase_id, WorkerDataArray* phase); + void print_count_values(LineBuffer& buf, G1GCPhaseTimes::GCPhases phase_id, WorkerDataArray* phase); + public: + G1GCPhasePrinter(G1GCPhaseTimes* phase_times) : _phase_times(phase_times) {} + void print(G1GCPhaseTimes::GCPhases phase_id); +}; + #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP