1/*
2 * Copyright (c) 2012, 2019, 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_GC_SHARED_GCTIMER_HPP
26#define SHARE_GC_SHARED_GCTIMER_HPP
27
28#include "memory/allocation.hpp"
29#include "utilities/macros.hpp"
30#include "utilities/ticks.hpp"
31
32class ConcurrentPhase;
33class GCPhase;
34class PausePhase;
35
36template <class E> class GrowableArray;
37
38class PhaseVisitor {
39 public:
40 virtual void visit(GCPhase* phase) = 0;
41};
42
43class 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:
58 void set_name(const char* name) { _name = name; }
59 const char* name() const { return _name; }
60
61 int level() const { return _level; }
62 void set_level(int level) { _level = level; }
63
64 const Ticks start() const { return _start; }
65 void set_start(const Ticks& time) { _start = time; }
66
67 const Ticks end() const { return _end; }
68 void set_end(const Ticks& time) { _end = time; }
69
70 PhaseType type() const { return _type; }
71 void set_type(PhaseType type) { _type = type; }
72
73 void accept(PhaseVisitor* visitor) {
74 visitor->visit(this);
75 }
76};
77
78class 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:
88 PhasesStack() { clear(); }
89 void clear();
90
91 void push(int phase_index);
92 int pop();
93 int count() const;
94};
95
96class 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
116 const Tickspan sum_of_pauses() const { return _sum_of_pauses; }
117 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
125class PhasesIterator {
126 public:
127 virtual bool has_next() = 0;
128 virtual GCPhase* next() = 0;
129};
130
131class 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
144 const Ticks gc_start() const { return _gc_start; }
145 const Ticks gc_end() const { return _gc_end; }
146
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
154class 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
160class 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:
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
175class TimePartitionPhasesIterator {
176 TimePartitions* _time_partitions;
177 int _next;
178
179 public:
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_GC_SHARED_GCTIMER_HPP
187