1 /*
   2  * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  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_SHARED_GCTIMER_HPP
  26 #define SHARE_VM_GC_SHARED_GCTIMER_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 #include "prims/jni_md.h"
  30 #include "utilities/macros.hpp"
  31 #include "utilities/ticks.hpp"
  32 
  33 class ConcurrentPhase;
  34 class GCPhase;
  35 class PausePhase;
  36 
  37 template <class E> class GrowableArray;
  38 
  39 class PhaseVisitor {
  40  public:
  41   virtual void visit(GCPhase* phase) = 0;
  42 };
  43 
  44 class GCPhase {
  45  public:
  46   enum PhaseType {
  47     PausePhaseType      = 0,
  48     ConcurrentPhaseType = 1
  49   };
  50 
  51  private:
  52   const char* _name;
  53   int _level;
  54   Ticks _start;
  55   Ticks _end;
  56   PhaseType _type;
  57 
  58  public:
  59   void set_name(const char* name) { _name = name; }
  60   const char* name() const { return _name; }
  61 
  62   int level() const { return _level; }
  63   void set_level(int level) { _level = level; }
  64 
  65   const Ticks start() const { return _start; }
  66   void set_start(const Ticks& time) { _start = time; }
  67 
  68   const Ticks end() const { return _end; }
  69   void set_end(const Ticks& time) { _end = time; }
  70 
  71   PhaseType type() const { return _type; }
  72   void set_type(PhaseType type) { _type = type; }
  73 
  74   void accept(PhaseVisitor* visitor) {
  75     visitor->visit(this);
  76   }
  77 };
  78 
  79 class PhasesStack {
  80  public:
  81   // Set to 6, since Reference processing needs it.
  82   static const int PHASE_LEVELS = 6;
  83 
  84  private:
  85   int _phase_indices[PHASE_LEVELS];
  86   int _next_phase_level;
  87 
  88  public:
  89   PhasesStack() { clear(); }
  90   void clear();
  91 
  92   void push(int phase_index);
  93   int pop();
  94   int count() const;
  95 };
  96 
  97 class TimePartitions {
  98   static const int INITIAL_CAPACITY = 10;
  99 
 100   GrowableArray<GCPhase>* _phases;
 101   PhasesStack _active_phases;
 102 
 103   Tickspan _sum_of_pauses;
 104   Tickspan _longest_pause;
 105 
 106  public:
 107   TimePartitions();
 108   ~TimePartitions();
 109   void clear();
 110 
 111   void report_gc_phase_start(const char* name, const Ticks& time, GCPhase::PhaseType type=GCPhase::PausePhaseType);
 112   void report_gc_phase_end(const Ticks& time, GCPhase::PhaseType type=GCPhase::PausePhaseType);
 113 
 114   int num_phases() const;
 115   GCPhase* phase_at(int index) const;
 116 
 117   const Tickspan sum_of_pauses() const { return _sum_of_pauses; }
 118   const Tickspan longest_pause() const { return _longest_pause; }
 119 
 120   bool has_active_phases();
 121 
 122  private:
 123   void update_statistics(GCPhase* phase);
 124 };
 125 
 126 class PhasesIterator {
 127  public:
 128   virtual bool has_next() = 0;
 129   virtual GCPhase* next() = 0;
 130 };
 131 
 132 class GCTimer : public ResourceObj {
 133   NOT_PRODUCT(friend class GCTimerTest;)
 134  protected:
 135   Ticks _gc_start;
 136   Ticks _gc_end;
 137   TimePartitions _time_partitions;
 138 
 139  public:
 140   virtual void register_gc_start(const Ticks& time = Ticks::now());
 141   virtual void register_gc_end(const Ticks& time = Ticks::now());
 142 
 143   void register_gc_phase_start(const char* name, const Ticks& time);
 144   void register_gc_phase_end(const Ticks& time);
 145 
 146   const Ticks gc_start() const { return _gc_start; }
 147   const Ticks gc_end() const { return _gc_end; }
 148 
 149   TimePartitions* time_partitions() { return &_time_partitions; }
 150 
 151  protected:
 152   void register_gc_pause_start(const char* name, const Ticks& time = Ticks::now());
 153   void register_gc_pause_end(const Ticks& time = Ticks::now());
 154 };
 155 
 156 class STWGCTimer : public GCTimer {
 157  public:
 158   virtual void register_gc_start(const Ticks& time = Ticks::now());
 159   virtual void register_gc_end(const Ticks& time = Ticks::now());
 160 };
 161 
 162 class ConcurrentGCTimer : public GCTimer {
 163   // ConcurrentGCTimer can't be used if there is an overlap between a pause phase and a concurrent phase.
 164   // _is_concurrent_phase_active is used to find above case.
 165   bool _is_concurrent_phase_active;
 166 
 167  public:
 168   ConcurrentGCTimer(): GCTimer(), _is_concurrent_phase_active(false) {};
 169 
 170   void register_gc_pause_start(const char* name);
 171   void register_gc_pause_end();
 172 
 173   void register_gc_concurrent_start(const char* name, const Ticks& time = Ticks::now());
 174   void register_gc_concurrent_end(const Ticks& time = Ticks::now());
 175 };
 176 
 177 class TimePartitionPhasesIterator {
 178   TimePartitions* _time_partitions;
 179   int _next;
 180 
 181  public:
 182   TimePartitionPhasesIterator(TimePartitions* time_partitions) : _time_partitions(time_partitions), _next(0) { }
 183 
 184   virtual bool has_next();
 185   virtual GCPhase* next();
 186 };
 187 
 188 #endif // SHARE_VM_GC_SHARED_GCTIMER_HPP