1 /*
2 * Copyright (c) 2018, 2019, Red Hat, Inc. 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_SHENANDOAH_HEURISTICS_SHENANDOAHHEURISTICS_HPP
26 #define SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHHEURISTICS_HPP
27
28 #include "gc/shenandoah/shenandoahHeap.hpp"
29 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
30 #include "gc/shenandoah/shenandoahSharedVariables.hpp"
31 #include "memory/allocation.hpp"
32 #include "runtime/globals_extension.hpp"
33
34 #define SHENANDOAH_ERGO_DISABLE_FLAG(name) \
35 do { \
36 if (FLAG_IS_DEFAULT(name) && (name)) { \
37 log_info(gc)("Heuristics ergonomically sets -XX:-" #name); \
38 FLAG_SET_DEFAULT(name, false); \
39 } \
40 } while (0)
41
42 #define SHENANDOAH_ERGO_ENABLE_FLAG(name) \
43 do { \
44 if (FLAG_IS_DEFAULT(name) && !(name)) { \
45 log_info(gc)("Heuristics ergonomically sets -XX:+" #name); \
46 FLAG_SET_DEFAULT(name, true); \
47 } \
48 } while (0)
49
50 #define SHENANDOAH_ERGO_OVERRIDE_DEFAULT(name, value) \
51 do { \
52 if (FLAG_IS_DEFAULT(name)) { \
53 log_info(gc)("Heuristics ergonomically sets -XX:" #name "=" #value); \
54 FLAG_SET_DEFAULT(name, value); \
55 } \
56 } while (0)
57
58 class ShenandoahCollectionSet;
59 class ShenandoahHeapRegion;
60
61 class ShenandoahHeuristics : public CHeapObj<mtGC> {
62 static const intx Concurrent_Adjust = -1; // recover from penalties
63 static const intx Degenerated_Penalty = 10; // how much to penalize average GC duration history on Degenerated GC
64 static const intx Full_Penalty = 20; // how much to penalize average GC duration history on Full GC
65
66 protected:
67 typedef struct {
68 ShenandoahHeapRegion* _region;
69 size_t _garbage;
70 } RegionData;
71
72 RegionData* _region_data;
73
74 uint _degenerated_cycles_in_a_row;
75 uint _successful_cycles_in_a_row;
76
77 double _cycle_start;
78 double _last_cycle_end;
79
80 size_t _gc_times_learned;
81 intx _gc_time_penalties;
82 TruncatedSeq* _gc_time_history;
83
84 // There may be many threads that contend to set this flag
85 ShenandoahSharedFlag _metaspace_oom;
86
87 static int compare_by_garbage(RegionData a, RegionData b);
88
89 virtual void choose_collection_set_from_regiondata(ShenandoahCollectionSet* set,
90 RegionData* data, size_t data_size,
91 size_t free) = 0;
92
93 void adjust_penalty(intx step);
94
95 public:
96 ShenandoahHeuristics();
97 virtual ~ShenandoahHeuristics();
98
99 void record_metaspace_oom() { _metaspace_oom.set(); }
100 void clear_metaspace_oom() { _metaspace_oom.unset(); }
101 bool has_metaspace_oom() const { return _metaspace_oom.is_set(); }
102
103 virtual void record_cycle_start();
104
105 virtual void record_cycle_end();
106
107 virtual bool should_start_gc();
108
109 virtual bool should_degenerate_cycle();
110
111 virtual void record_success_concurrent();
112
113 virtual void record_success_degenerated();
114
115 virtual void record_success_full();
116
117 virtual void record_allocation_failure_gc();
118
119 virtual void record_requested_gc();
120
121 virtual void choose_collection_set(ShenandoahCollectionSet* collection_set);
122
123 virtual bool can_unload_classes();
124 virtual bool should_unload_classes();
125
126 virtual const char* name() = 0;
127 virtual bool is_diagnostic() = 0;
128 virtual bool is_experimental() = 0;
129 virtual void initialize();
130
131 double time_since_last_gc() const;
132 };
133
134 #endif // SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHHEURISTICS_HPP
|
1 /*
2 * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved.
3 * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #ifndef SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHHEURISTICS_HPP
27 #define SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHHEURISTICS_HPP
28
29 #include "gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp"
30 #include "gc/shenandoah/shenandoahSharedVariables.hpp"
31 #include "memory/allocation.hpp"
32 #include "runtime/globals_extension.hpp"
33 #include "utilities/numberSeq.hpp"
34
35 #define SHENANDOAH_ERGO_DISABLE_FLAG(name) \
36 do { \
37 if (FLAG_IS_DEFAULT(name) && (name)) { \
38 log_info(gc)("Heuristics ergonomically sets -XX:-" #name); \
39 FLAG_SET_DEFAULT(name, false); \
40 } \
41 } while (0)
42
43 #define SHENANDOAH_ERGO_ENABLE_FLAG(name) \
44 do { \
45 if (FLAG_IS_DEFAULT(name) && !(name)) { \
46 log_info(gc)("Heuristics ergonomically sets -XX:+" #name); \
47 FLAG_SET_DEFAULT(name, true); \
48 } \
49 } while (0)
50
51 #define SHENANDOAH_ERGO_OVERRIDE_DEFAULT(name, value) \
52 do { \
53 if (FLAG_IS_DEFAULT(name)) { \
54 log_info(gc)("Heuristics ergonomically sets -XX:" #name "=" #value); \
55 FLAG_SET_DEFAULT(name, value); \
56 } \
57 } while (0)
58
59 class ShenandoahCollectionSet;
60 class ShenandoahHeapRegion;
61
62 /*
63 * Shenandoah heuristics are primarily responsible for deciding when to start
64 * a collection cycle and choosing which regions will be evacuated during the
65 * cycle.
66 */
67 class ShenandoahHeuristics : public CHeapObj<mtGC> {
68 static const intx Concurrent_Adjust = -1; // recover from penalties
69 static const intx Degenerated_Penalty = 10; // how much to penalize average GC duration history on Degenerated GC
70 static const intx Full_Penalty = 20; // how much to penalize average GC duration history on Full GC
71
72 #ifdef ASSERT
73 enum UnionTag {
74 is_uninitialized, is_garbage, is_live_data
75 };
76 #endif
77
78 protected:
79 static const uint Moving_Average_Samples = 10; // Number of samples to store in moving averages
80
81 class RegionData {
82 private:
83 ShenandoahHeapRegion* _region;
84 union {
85 size_t _garbage; // Not used by old-gen heuristics.
86 size_t _live_data; // Only used for old-gen heuristics, which prioritizes retention of _live_data over garbage reclaim
87 } _region_union;
88 #ifdef ASSERT
89 UnionTag _union_tag;
90 #endif
91 public:
92
93 inline void clear() {
94 _region = nullptr;
95 _region_union._garbage = 0;
96 #ifdef ASSERT
97 _union_tag = is_uninitialized;
98 #endif
99 }
100
101 inline void set_region_and_garbage(ShenandoahHeapRegion* region, size_t garbage) {
102 _region = region;
103 _region_union._garbage = garbage;
104 #ifdef ASSERT
105 _union_tag = is_garbage;
106 #endif
107 }
108
109 inline void set_region_and_livedata(ShenandoahHeapRegion* region, size_t live) {
110 _region = region;
111 _region_union._live_data = live;
112 #ifdef ASSERT
113 _union_tag = is_live_data;
114 #endif
115 }
116
117 inline ShenandoahHeapRegion* get_region() const {
118 assert(_union_tag != is_uninitialized, "Cannot fetch region from uninitialized RegionData");
119 return _region;
120 }
121
122 inline size_t get_garbage() const {
123 assert(_union_tag == is_garbage, "Invalid union fetch");
124 return _region_union._garbage;
125 }
126
127 inline size_t get_livedata() const {
128 assert(_union_tag == is_live_data, "Invalid union fetch");
129 return _region_union._live_data;
130 }
131 };
132
133 // Source of information about the memory space managed by this heuristic
134 ShenandoahSpaceInfo* _space_info;
135
136 // Depending on generation mode, region data represents the results of the relevant
137 // most recently completed marking pass:
138 // - in GLOBAL mode, global marking pass
139 // - in OLD mode, old-gen marking pass
140 // - in YOUNG mode, young-gen marking pass
141 //
142 // Note that there is some redundancy represented in region data because
143 // each instance is an array large enough to hold all regions. However,
144 // any region in young-gen is not in old-gen. And any time we are
145 // making use of the GLOBAL data, there is no need to maintain the
146 // YOUNG or OLD data. Consider this redundancy of data structure to
147 // have negligible cost unless proven otherwise.
148 RegionData* _region_data;
149
150 size_t _guaranteed_gc_interval;
151
152 double _cycle_start;
153 double _last_cycle_end;
154
155 size_t _gc_times_learned;
156 intx _gc_time_penalties;
157 TruncatedSeq* _gc_cycle_time_history;
158
159 // There may be many threads that contend to set this flag
160 ShenandoahSharedFlag _metaspace_oom;
161
162 static int compare_by_garbage(RegionData a, RegionData b);
163
164 virtual void choose_collection_set_from_regiondata(ShenandoahCollectionSet* set,
165 RegionData* data, size_t data_size,
166 size_t free) = 0;
167
168 void adjust_penalty(intx step);
169
170 public:
171 ShenandoahHeuristics(ShenandoahSpaceInfo* space_info);
172 virtual ~ShenandoahHeuristics();
173
174 void record_metaspace_oom() { _metaspace_oom.set(); }
175 void clear_metaspace_oom() { _metaspace_oom.unset(); }
176 bool has_metaspace_oom() const { return _metaspace_oom.is_set(); }
177
178 void set_guaranteed_gc_interval(size_t guaranteed_gc_interval) {
179 _guaranteed_gc_interval = guaranteed_gc_interval;
180 }
181
182 virtual void record_cycle_start();
183
184 virtual void record_cycle_end();
185
186 virtual bool should_start_gc();
187
188 virtual bool should_degenerate_cycle();
189
190 virtual void record_success_concurrent();
191
192 virtual void record_success_degenerated();
193
194 virtual void record_success_full();
195
196 virtual void record_allocation_failure_gc();
197
198 virtual void record_requested_gc();
199
200 virtual void choose_collection_set(ShenandoahCollectionSet* collection_set);
201
202 virtual bool can_unload_classes();
203
204 // This indicates whether or not the current cycle should unload classes.
205 // It does NOT indicate that a cycle should be started.
206 virtual bool should_unload_classes();
207
208 virtual const char* name() = 0;
209 virtual bool is_diagnostic() = 0;
210 virtual bool is_experimental() = 0;
211 virtual void initialize();
212
213 double elapsed_cycle_time() const;
214
215 // Format prefix and emit log message indicating a GC cycle hs been triggered
216 void log_trigger(const char* fmt, ...) ATTRIBUTE_PRINTF(2, 3);
217 };
218
219 #endif // SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHHEURISTICS_HPP
|