1 /*
2  * Copyright (c) 2012, 2018, 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 "utilities/macros.hpp"
30 #include "utilities/ticks.hpp"
31 
32 class ConcurrentPhase;
33 class GCPhase;
34 class PausePhase;
35 
36 template <class E> class GrowableArray;
37 
38 class PhaseVisitor {
39  public:
40   virtual void visit(GCPhase* phase) = 0;
41 };
42 
43 class GCPhase {
44  public:
45   enum PhaseType {
46     PausePhaseType      = 0,
47     ConcurrentPhaseType = 1
48   };
49 
50  private:
51   const char* _name;
52   int _level;
53   Ticks _start;
54   Ticks _end;
55   PhaseType _type;
56 
57  public:
set_name(const char * name)58   void set_name(const char* name) { _name = name; }
name() const59   const char* name() const { return _name; }
60 
level() const61   int level() const { return _level; }
set_level(int level)62   void set_level(int level) { _level = level; }
63 
start() const64   const Ticks start() const { return _start; }
set_start(const Ticks & time)65   void set_start(const Ticks& time) { _start = time; }
66 
end() const67   const Ticks end() const { return _end; }
set_end(const Ticks & time)68   void set_end(const Ticks& time) { _end = time; }
69 
type() const70   PhaseType type() const { return _type; }
set_type(PhaseType type)71   void set_type(PhaseType type) { _type = type; }
72 
accept(PhaseVisitor * visitor)73   void accept(PhaseVisitor* visitor) {
74     visitor->visit(this);
75   }
76 };
77 
78 class PhasesStack {
79  public:
80   // Set to 6, since Reference processing needs it.
81   static const int PHASE_LEVELS = 6;
82 
83  private:
84   int _phase_indices[PHASE_LEVELS];
85   int _next_phase_level;
86 
87  public:
PhasesStack()88   PhasesStack() { clear(); }
89   void clear();
90 
91   void push(int phase_index);
92   int pop();
93   int count() const;
94 };
95 
96 class TimePartitions {
97   static const int INITIAL_CAPACITY = 10;
98 
99   GrowableArray<GCPhase>* _phases;
100   PhasesStack _active_phases;
101 
102   Tickspan _sum_of_pauses;
103   Tickspan _longest_pause;
104 
105  public:
106   TimePartitions();
107   ~TimePartitions();
108   void clear();
109 
110   void report_gc_phase_start(const char* name, const Ticks& time, GCPhase::PhaseType type=GCPhase::PausePhaseType);
111   void report_gc_phase_end(const Ticks& time, GCPhase::PhaseType type=GCPhase::PausePhaseType);
112 
113   int num_phases() const;
114   GCPhase* phase_at(int index) const;
115 
sum_of_pauses() const116   const Tickspan sum_of_pauses() const { return _sum_of_pauses; }
longest_pause() const117   const Tickspan longest_pause() const { return _longest_pause; }
118 
119   bool has_active_phases();
120 
121  private:
122   void update_statistics(GCPhase* phase);
123 };
124 
125 class PhasesIterator {
126  public:
127   virtual bool has_next() = 0;
128   virtual GCPhase* next() = 0;
129 };
130 
131 class GCTimer : public ResourceObj {
132  protected:
133   Ticks _gc_start;
134   Ticks _gc_end;
135   TimePartitions _time_partitions;
136 
137  public:
138   virtual void register_gc_start(const Ticks& time = Ticks::now());
139   virtual void register_gc_end(const Ticks& time = Ticks::now());
140 
141   void register_gc_phase_start(const char* name, const Ticks& time);
142   void register_gc_phase_end(const Ticks& time);
143 
gc_start() const144   const Ticks gc_start() const { return _gc_start; }
gc_end() const145   const Ticks gc_end() const { return _gc_end; }
146 
time_partitions()147   TimePartitions* time_partitions() { return &_time_partitions; }
148 
149  protected:
150   void register_gc_pause_start(const char* name, const Ticks& time = Ticks::now());
151   void register_gc_pause_end(const Ticks& time = Ticks::now());
152 };
153 
154 class STWGCTimer : public GCTimer {
155  public:
156   virtual void register_gc_start(const Ticks& time = Ticks::now());
157   virtual void register_gc_end(const Ticks& time = Ticks::now());
158 };
159 
160 class ConcurrentGCTimer : public GCTimer {
161   // ConcurrentGCTimer can't be used if there is an overlap between a pause phase and a concurrent phase.
162   // _is_concurrent_phase_active is used to find above case.
163   bool _is_concurrent_phase_active;
164 
165  public:
ConcurrentGCTimer()166   ConcurrentGCTimer(): GCTimer(), _is_concurrent_phase_active(false) {};
167 
168   void register_gc_pause_start(const char* name, const Ticks& time = Ticks::now());
169   void register_gc_pause_end(const Ticks& time = Ticks::now());
170 
171   void register_gc_concurrent_start(const char* name, const Ticks& time = Ticks::now());
172   void register_gc_concurrent_end(const Ticks& time = Ticks::now());
173 };
174 
175 class TimePartitionPhasesIterator {
176   TimePartitions* _time_partitions;
177   int _next;
178 
179  public:
TimePartitionPhasesIterator(TimePartitions * time_partitions)180   TimePartitionPhasesIterator(TimePartitions* time_partitions) : _time_partitions(time_partitions), _next(0) { }
181 
182   virtual bool has_next();
183   virtual GCPhase* next();
184 };
185 
186 #endif // SHARE_VM_GC_SHARED_GCTIMER_HPP
187