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 #ifdef ASSERT
94 inline void clear() {
95 _union_tag = is_uninitialized;
96 }
97 #endif
98
99 inline void set_region_and_garbage(ShenandoahHeapRegion* region, size_t garbage) {
100 _region = region;
101 _region_union._garbage = garbage;
102 #ifdef ASSERT
103 _union_tag = is_garbage;
104 #endif
105 }
106
107 inline void set_region_and_livedata(ShenandoahHeapRegion* region, size_t live) {
108 _region = region;
109 _region_union._live_data = live;
110 #ifdef ASSERT
111 _union_tag = is_live_data;
112 #endif
113 }
114
115 inline ShenandoahHeapRegion* get_region() const {
116 #ifdef ASSERT
117 assert(_union_tag != is_uninitialized, "Cannot fetch region from uninialized RegionData");
118 #endif
119 return _region;
120 }
121
122 inline size_t get_garbage() const {
123 #ifdef ASSERT
124 assert(_union_tag == is_garbage, "Invalid union fetch");
125 #endif
126 return _region_union._garbage;
127 }
128
129 inline size_t get_livedata() const {
130 #ifdef ASSERT
131 assert(_union_tag == is_live_data, "Invalid union fetch");
132 #endif
133 return _region_union._live_data;
134 }
135 };
136
137 // Source of information about the memory space managed by this heuristic
138 ShenandoahSpaceInfo* _space_info;
139
140 // Depending on generation mode, region data represents the results of the relevant
141 // most recently completed marking pass:
142 // - in GLOBAL mode, global marking pass
143 // - in OLD mode, old-gen marking pass
144 // - in YOUNG mode, young-gen marking pass
145 //
146 // Note that there is some redundancy represented in region data because
147 // each instance is an array large enough to hold all regions. However,
148 // any region in young-gen is not in old-gen. And any time we are
149 // making use of the GLOBAL data, there is no need to maintain the
150 // YOUNG or OLD data. Consider this redundancy of data structure to
151 // have negligible cost unless proven otherwise.
152 RegionData* _region_data;
153
154 size_t _guaranteed_gc_interval;
155
156 double _cycle_start;
157 double _last_cycle_end;
158
159 size_t _gc_times_learned;
160 intx _gc_time_penalties;
161 TruncatedSeq* _gc_cycle_time_history;
162
163 // There may be many threads that contend to set this flag
164 ShenandoahSharedFlag _metaspace_oom;
165
166 static int compare_by_garbage(RegionData a, RegionData b);
167
168 virtual void choose_collection_set_from_regiondata(ShenandoahCollectionSet* set,
169 RegionData* data, size_t data_size,
170 size_t free) = 0;
171
172 void adjust_penalty(intx step);
173
174 public:
175 ShenandoahHeuristics(ShenandoahSpaceInfo* space_info);
176 virtual ~ShenandoahHeuristics();
177
178 void record_metaspace_oom() { _metaspace_oom.set(); }
179 void clear_metaspace_oom() { _metaspace_oom.unset(); }
180 bool has_metaspace_oom() const { return _metaspace_oom.is_set(); }
181
182 void set_guaranteed_gc_interval(size_t guaranteed_gc_interval) {
183 _guaranteed_gc_interval = guaranteed_gc_interval;
184 }
185
186 virtual void record_cycle_start();
187
188 virtual void record_cycle_end();
189
190 virtual bool should_start_gc();
191
192 virtual bool should_degenerate_cycle();
193
194 virtual void record_success_concurrent();
195
196 virtual void record_success_degenerated();
197
198 virtual void record_success_full();
199
200 virtual void record_allocation_failure_gc();
201
202 virtual void record_requested_gc();
203
204 virtual void choose_collection_set(ShenandoahCollectionSet* collection_set);
205
206 virtual bool can_unload_classes();
207
208 // This indicates whether or not the current cycle should unload classes.
209 // It does NOT indicate that a cycle should be started.
210 virtual bool should_unload_classes();
211
212 virtual const char* name() = 0;
213 virtual bool is_diagnostic() = 0;
214 virtual bool is_experimental() = 0;
215 virtual void initialize();
216
217 double elapsed_cycle_time() const;
218 };
219
220 #endif // SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHHEURISTICS_HPP
|