< prev index next >

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

Print this page




  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
  26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
  27 
  28 #include "gc_interface/gcCause.hpp"
  29 
  30 class LineBuffer;
  31 
  32 template <class T>
  33 class WorkerDataArray  : public CHeapObj<mtGC> {

  34   T*          _data;
  35   uint        _length;
  36   const char* _title;
  37   bool        _print_sum;
  38   int         _log_level;
  39   uint        _indent_level;
  40   bool        _enabled;
  41 
  42   WorkerDataArray<size_t>* _sub_count;
  43 
  44   NOT_PRODUCT(T uninitialized();)
  45 
  46   // We are caching the sum and average to only have to calculate them once.
  47   // This is not done in an MT-safe way. It is intended to allow single
  48   // threaded code to call sum() and average() multiple times in any order
  49   // without having to worry about the cost.
  50   bool   _has_new_data;
  51   T      _sum;


  52   double _average;
  53 
  54   void log_value(LineBuffer& buf, T value);
  55 
  56  public:
  57   WorkerDataArray(uint length, const char* title, bool print_sum, int log_level, uint indent_level);
  58 
  59   ~WorkerDataArray();
  60 
  61   void link_sub_count_array(WorkerDataArray<size_t>* sub_count) {
  62     _sub_count = sub_count;
  63   }
  64 


  65   void set(uint worker_i, T value) {
  66     assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
  67     assert(_data[worker_i] == WorkerDataArray<T>::uninitialized(), err_msg("Overwriting data for worker %d in %s", worker_i, _title));
  68     _data[worker_i] = value;
  69     _has_new_data = true;
  70   }
  71 
  72   void set_sub_count(uint worker_i, size_t value) {
  73     assert(_sub_count != NULL, "No sub count");
  74     _sub_count->set(worker_i, value);
  75   }
  76 
  77   size_t sub_count_sum() {
  78     assert(_sub_count != NULL, "No sub count");
  79     return _sub_count->sum();
  80   }
  81 
  82   T get(uint worker_i) {
  83     assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
  84     assert(_data[worker_i] != WorkerDataArray<T>::uninitialized(), err_msg("No data to add to for worker %d", worker_i));
  85     return _data[worker_i];
  86   }
  87 
  88   void add(uint worker_i, T value) {
  89     assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
  90     assert(_data[worker_i] != WorkerDataArray<T>::uninitialized(), err_msg("No data to add to for worker %d", worker_i));
  91     _data[worker_i] += value;
  92     _has_new_data = true;
  93   }
  94 
  95   double average(){
  96     if (_has_new_data) {
  97       calculate_totals();
  98     }
  99     return _average;
 100   }
 101 
 102   T sum() {
 103     if (_has_new_data) {
 104       calculate_totals();
 105     }
 106     return _sum;
 107   }
 108 
 109   void print();








 110 
 111   void reset() PRODUCT_RETURN;
 112   void verify() PRODUCT_RETURN;
 113 
 114   void set_enabled(bool enabled) { _enabled = enabled; }
 115 
 116   int log_level() { return _log_level;  }
 117 
 118  private:
 119 
 120   void calculate_totals(){




 121     _sum = (T)0;


 122     for (uint i = 0; i < _length; ++i) {
 123       _sum += _data[i];



 124     }
 125     _average = (double)_sum / (double)_length;
 126     _has_new_data = false;
 127   }
 128 };
 129 
 130 class G1GCPhaseTimes : public CHeapObj<mtGC> {


 131   uint _active_gc_threads;
 132   uint _max_gc_threads;
 133 
 134  public:
 135   enum GCPhases {
 136     GCWorkerStart,
 137     ExtRootScan,
 138     SATBFiltering,
 139     UpdateRS,
 140     ScanRS,
 141     CodeRoots,
 142     ObjCopy,
 143     Termination,
 144     Other,
 145     GCWorkerTotal,
 146     GCWorkerEnd,
 147     StringDedupQueueFixup,
 148     StringDedupTableFixup,
 149     RedirtyCards,
 150     Sentinel


 189   double _cur_fast_reclaim_humongous_time_ms;
 190   double _cur_fast_reclaim_humongous_register_time_ms;
 191   size_t _cur_fast_reclaim_humongous_total;
 192   size_t _cur_fast_reclaim_humongous_candidates;
 193   size_t _cur_fast_reclaim_humongous_reclaimed;
 194 
 195   double _cur_verify_before_time_ms;
 196   double _cur_verify_after_time_ms;
 197 
 198   // Helper methods for detailed logging
 199   void print_stats(int level, const char* str, double value);
 200   void print_stats(int level, const char* str, size_t value);
 201   void print_stats(int level, const char* str, double value, uint workers);
 202 
 203  public:
 204   G1GCPhaseTimes(uint max_gc_threads);
 205   void note_gc_start(uint active_gc_threads, bool mark_in_progress);
 206   void note_gc_end();
 207   void print(double pause_time_sec);
 208 
 209   void record_time(GCPhases phase, uint worker_i, double time) {
 210     _gc_phases[phase]->set(worker_i, time);

 211   }
 212 
 213   void add_time(GCPhases phase, uint worker_i, double time) {
 214     _gc_phases[phase]->add(worker_i, time);

 215   }
 216 
 217   void record_sub_count(GCPhases phase, uint worker_i, size_t count) {
 218     _gc_phases[phase]->set_sub_count(worker_i, count);
 219   }
 220 
 221   double average_time(GCPhases phase) {
 222     return _gc_phases[phase]->average();

 223   }
 224 
 225   size_t sub_count_sum(GCPhases phase) {
 226     return _gc_phases[phase]->sub_count_sum();











 227   }
 228 



































 229   void record_clear_ct_time(double ms) {
 230     _cur_clear_ct_time_ms = ms;
 231   }
 232 
 233   void record_par_time(double ms) {
 234     _cur_collection_par_time_ms = ms;
 235   }
 236 
 237   void record_code_root_fixup_time(double ms) {
 238     _cur_collection_code_root_fixup_time_ms = ms;
 239   }
 240 
 241   void record_strong_code_root_purge_time(double ms) {
 242     _cur_strong_code_root_purge_time_ms = ms;
 243   }
 244 
 245   void record_evac_fail_recalc_used_time(double ms) {
 246     _cur_evac_fail_recalc_used = ms;
 247   }
 248 


 343     return _recorded_non_young_cset_choice_time_ms;
 344   }
 345 
 346   double non_young_free_cset_time_ms() {
 347     return _recorded_non_young_free_cset_time_ms;
 348   }
 349 
 350   double fast_reclaim_humongous_time_ms() {
 351     return _cur_fast_reclaim_humongous_time_ms;
 352   }
 353 };
 354 
 355 class G1GCPhaseTimesTracker : public StackObj {
 356   double _start_time;
 357   G1GCPhaseTimes::GCPhases _phase;
 358   G1GCPhaseTimes* _phase_times;
 359   uint _worker_id;
 360 public:
 361   G1GCPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCPhases phase, uint worker_id);
 362   ~G1GCPhaseTimesTracker();












 363 };
 364 
 365 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP


  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
  26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
  27 
  28 #include "gc_interface/gcCause.hpp"
  29 
  30 class LineBuffer;
  31 
  32 template <class T>
  33 class WorkerDataArray  : public CHeapObj<mtGC> {
  34   friend class G1GCPhasePrinter;
  35   T*          _data;
  36   uint        _length;
  37   const char* _title;
  38   bool        _print_sum;
  39   int         _log_level;
  40   uint        _indent_level;
  41   bool        _enabled;
  42 
  43   WorkerDataArray<size_t>* _sub_count;
  44 
  45   NOT_PRODUCT(T uninitialized();)
  46 
  47   // We are caching the sum and average to only have to calculate them once.
  48   // This is not done in an MT-safe way. It is intended to allow single
  49   // threaded code to call sum() and average() multiple times in any order
  50   // without having to worry about the cost.
  51   bool   _has_new_data;
  52   T      _sum;
  53   T      _min;
  54   T      _max;
  55   double _average;
  56 


  57  public:
  58   WorkerDataArray(uint length, const char* title, bool print_sum, int log_level, uint indent_level);
  59 
  60   ~WorkerDataArray();
  61 
  62   void link_sub_count_array(WorkerDataArray<size_t>* sub_count) {
  63     _sub_count = sub_count;
  64   }
  65 
  66   WorkerDataArray<size_t>* sub_count() { return _sub_count; }
  67 
  68   void set(uint worker_i, T value) {
  69     assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
  70     assert(_data[worker_i] == WorkerDataArray<T>::uninitialized(), err_msg("Overwriting data for worker %d in %s", worker_i, _title));
  71     _data[worker_i] = value;
  72     _has_new_data = true;
  73   }
  74 
  75   void set_sub_count(uint worker_i, size_t value) {
  76     assert(_sub_count != NULL, "No sub count");
  77     _sub_count->set(worker_i, value);
  78   }
  79 





  80   T get(uint worker_i) {
  81     assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
  82     assert(_data[worker_i] != WorkerDataArray<T>::uninitialized(), err_msg("No data to add to for worker %d", worker_i));
  83     return _data[worker_i];
  84   }
  85 
  86   void add(uint worker_i, T value) {
  87     assert(worker_i < _length, err_msg("Worker %d is greater than max: %d", worker_i, _length));
  88     assert(_data[worker_i] != WorkerDataArray<T>::uninitialized(), err_msg("No data to add to for worker %d", worker_i));
  89     _data[worker_i] += value;
  90     _has_new_data = true;
  91   }
  92 
  93   double average(){

  94     calculate_totals();

  95     return _average;
  96   }
  97 
  98   T sum() {

  99     calculate_totals();

 100     return _sum;
 101   }
 102 
 103   T minimum() {
 104     calculate_totals();
 105     return _min;
 106   }
 107 
 108   T maximum() {
 109     calculate_totals();
 110     return _max;
 111   }
 112 
 113   void reset() PRODUCT_RETURN;
 114   void verify() PRODUCT_RETURN;
 115 
 116   void set_enabled(bool enabled) { _enabled = enabled; }
 117 
 118   int log_level() { return _log_level;  }
 119 
 120  private:
 121 
 122   void calculate_totals(){
 123     if (!_has_new_data) {
 124       return;
 125     }
 126 
 127     _sum = (T)0;
 128     _min = _data[0];
 129     _max = _min;
 130     for (uint i = 0; i < _length; ++i) {
 131       T val = _data[i];
 132       _sum += val;
 133       _min = MIN2(_min, val);
 134       _max = MAX2(_max, val);
 135     }
 136     _average = (double)_sum / (double)_length;
 137     _has_new_data = false;
 138   }
 139 };
 140 
 141 class G1GCPhaseTimes : public CHeapObj<mtGC> {
 142   friend class G1GCPhasePrinter;
 143 
 144   uint _active_gc_threads;
 145   uint _max_gc_threads;
 146 
 147  public:
 148   enum GCPhases {
 149     GCWorkerStart,
 150     ExtRootScan,
 151     SATBFiltering,
 152     UpdateRS,
 153     ScanRS,
 154     CodeRoots,
 155     ObjCopy,
 156     Termination,
 157     Other,
 158     GCWorkerTotal,
 159     GCWorkerEnd,
 160     StringDedupQueueFixup,
 161     StringDedupTableFixup,
 162     RedirtyCards,
 163     Sentinel


 202   double _cur_fast_reclaim_humongous_time_ms;
 203   double _cur_fast_reclaim_humongous_register_time_ms;
 204   size_t _cur_fast_reclaim_humongous_total;
 205   size_t _cur_fast_reclaim_humongous_candidates;
 206   size_t _cur_fast_reclaim_humongous_reclaimed;
 207 
 208   double _cur_verify_before_time_ms;
 209   double _cur_verify_after_time_ms;
 210 
 211   // Helper methods for detailed logging
 212   void print_stats(int level, const char* str, double value);
 213   void print_stats(int level, const char* str, size_t value);
 214   void print_stats(int level, const char* str, double value, uint workers);
 215 
 216  public:
 217   G1GCPhaseTimes(uint max_gc_threads);
 218   void note_gc_start(uint active_gc_threads, bool mark_in_progress);
 219   void note_gc_end();
 220   void print(double pause_time_sec);
 221 
 222   // record the time a phase took in seconds
 223   void record_time_secs(GCPhases phase, uint worker_i, double secs) {
 224     _gc_phases[phase]->set(worker_i, secs);
 225   }
 226 
 227   // add a number of seconds to a phase
 228   void add_time_secs(GCPhases phase, uint worker_i, double secs) {
 229     _gc_phases[phase]->add(worker_i, secs);
 230   }
 231 
 232   void record_sub_count(GCPhases phase, uint worker_i, size_t count) {
 233     _gc_phases[phase]->set_sub_count(worker_i, count);
 234   }
 235 
 236   // return the average time for a phase in milliseconds
 237   double average_time_ms(GCPhases phase) {
 238     return _gc_phases[phase]->average() * 1000.0;
 239   }
 240 
 241   size_t sub_count_sum(GCPhases phase) {
 242     assert(_gc_phases[phase]->sub_count() != NULL, "No sub count");
 243     return _gc_phases[phase]->sub_count()->sum();
 244   }
 245 
 246  private:
 247 
 248   double get_time_ms(GCPhases phase, uint worker_i) {
 249     return _gc_phases[phase]->get(worker_i) * 1000.0;
 250   }
 251 
 252   double sum_time_ms(GCPhases phase) {
 253     return _gc_phases[phase]->sum() * 1000.0;
 254   }
 255 
 256   double min_time_ms(GCPhases phase) {
 257     return _gc_phases[phase]->minimum() * 1000.0;
 258   }
 259 
 260   double max_time_ms(GCPhases phase) {
 261     return _gc_phases[phase]->maximum() * 1000.0;
 262   }
 263 
 264   size_t get_sub_count(GCPhases phase, uint worker_i) {
 265     assert(_gc_phases[phase]->sub_count() != NULL, "No sub count");
 266     return _gc_phases[phase]->sub_count()->get(worker_i);
 267   }
 268 
 269   size_t sum_sub_count(GCPhases phase) {
 270     assert(_gc_phases[phase]->sub_count() != NULL, "No sub count");
 271     return _gc_phases[phase]->sub_count()->sum();
 272   }
 273 
 274   double average_sub_count(GCPhases phase) {
 275     assert(_gc_phases[phase]->sub_count() != NULL, "No sub count");
 276     return _gc_phases[phase]->sub_count()->average();
 277   }
 278 
 279   size_t min_sub_count(GCPhases phase) {
 280     assert(_gc_phases[phase]->sub_count() != NULL, "No sub count");
 281     return _gc_phases[phase]->sub_count()->minimum();
 282   }
 283 
 284   size_t max_sub_count(GCPhases phase) {
 285     assert(_gc_phases[phase]->sub_count() != NULL, "No sub count");
 286     return _gc_phases[phase]->sub_count()->maximum();
 287   }
 288 
 289  public:
 290 
 291   void record_clear_ct_time(double ms) {
 292     _cur_clear_ct_time_ms = ms;
 293   }
 294 
 295   void record_par_time(double ms) {
 296     _cur_collection_par_time_ms = ms;
 297   }
 298 
 299   void record_code_root_fixup_time(double ms) {
 300     _cur_collection_code_root_fixup_time_ms = ms;
 301   }
 302 
 303   void record_strong_code_root_purge_time(double ms) {
 304     _cur_strong_code_root_purge_time_ms = ms;
 305   }
 306 
 307   void record_evac_fail_recalc_used_time(double ms) {
 308     _cur_evac_fail_recalc_used = ms;
 309   }
 310 


 405     return _recorded_non_young_cset_choice_time_ms;
 406   }
 407 
 408   double non_young_free_cset_time_ms() {
 409     return _recorded_non_young_free_cset_time_ms;
 410   }
 411 
 412   double fast_reclaim_humongous_time_ms() {
 413     return _cur_fast_reclaim_humongous_time_ms;
 414   }
 415 };
 416 
 417 class G1GCPhaseTimesTracker : public StackObj {
 418   double _start_time;
 419   G1GCPhaseTimes::GCPhases _phase;
 420   G1GCPhaseTimes* _phase_times;
 421   uint _worker_id;
 422 public:
 423   G1GCPhaseTimesTracker(G1GCPhaseTimes* phase_times, G1GCPhaseTimes::GCPhases phase, uint worker_id);
 424   ~G1GCPhaseTimesTracker();
 425 };
 426 
 427 class G1GCPhasePrinter : public StackObj {
 428   G1GCPhaseTimes* _phase_times;
 429   void print_single_length(G1GCPhaseTimes::GCPhases phase_id, WorkerDataArray<double>* phase);
 430   void print_multi_length(G1GCPhaseTimes::GCPhases phase_id, WorkerDataArray<double>* phase);
 431   void print_sub_count(G1GCPhaseTimes::GCPhases phase_id, WorkerDataArray<size_t>* sub_count);
 432   void print_time_values(LineBuffer& buf, G1GCPhaseTimes::GCPhases phase_id, WorkerDataArray<double>* phase);
 433   void print_count_values(LineBuffer& buf, G1GCPhaseTimes::GCPhases phase_id, WorkerDataArray<size_t>* phase);
 434  public:
 435   G1GCPhasePrinter(G1GCPhaseTimes* phase_times) : _phase_times(phase_times) {}
 436   void print(G1GCPhaseTimes::GCPhases phase_id);
 437 };
 438 
 439 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1GCPHASETIMESLOG_HPP
< prev index next >