33 _target_occupancy(target_occupancy) {
34 assert(_ihop_percent >= 0.0 && _ihop_percent <= 100.0, "Initial IHOP value must be between 0 and 100 but is %.3f", initial_ihop_percent);
35 }
36
37 G1StaticIHOPControl::G1StaticIHOPControl(double ihop_percent, size_t target_occupancy) :
38 G1IHOPControl(ihop_percent, target_occupancy),
39 _last_allocation_time_s(0.0),
40 _last_allocated_bytes(0),
41 _last_marking_length_s(0.0) {
42 assert(_target_occupancy > 0, "Target occupancy must be larger than zero.");
43 }
44
45 void G1StaticIHOPControl::print() {
46 ergo_verbose6(ErgoIHOP,
47 "basic information",
48 ergo_format_reason("value update")
49 ergo_format_byte_perc("threshold")
50 ergo_format_byte("target occupancy")
51 ergo_format_byte("current occupancy")
52 ergo_format_double("recent old gen allocation rate")
53 ergo_format_ms("recent marking phase length"),
54 get_conc_mark_start_threshold(),
55 (double) get_conc_mark_start_threshold() / _target_occupancy * 100.0,
56 _target_occupancy,
57 G1CollectedHeap::heap()->used(),
58 _last_allocation_time_s > 0.0 ? _last_allocated_bytes / _last_allocation_time_s : 0.0,
59 _last_marking_length_s * 1000.0);
60 }
61
62 #ifndef PRODUCT
63 static void test_update(G1IHOPControl* ctrl, double alloc_time, size_t alloc_amount, size_t young_size, double mark_time) {
64 for (int i = 0; i < 100; i++) {
65 ctrl->update_allocation_info(alloc_time, alloc_amount, young_size);
66 ctrl->update_time_to_mixed(mark_time);
67 }
68 }
69
70 void G1StaticIHOPControl::test() {
71 size_t const initial_ihop = 45;
72
73 G1StaticIHOPControl ctrl(initial_ihop, 100);
74 size_t threshold;
75
76 threshold = ctrl.get_conc_mark_start_threshold();
77 assert(threshold == initial_ihop,
78 "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
79
83 "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
84
85 ctrl.update_time_to_mixed(1000.0);
86 threshold = ctrl.get_conc_mark_start_threshold();
87 assert(threshold == initial_ihop,
88 "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
89
90 // Whatever we pass, the IHOP value must stay the same.
91 test_update(&ctrl, 2, 10, 10, 3);
92 threshold = ctrl.get_conc_mark_start_threshold();
93 assert(threshold == initial_ihop,
94 "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
95
96 test_update(&ctrl, 12, 10, 10, 3);
97 threshold = ctrl.get_conc_mark_start_threshold();
98 assert(threshold == initial_ihop,
99 "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
100 }
101 #endif
102
103 #ifndef PRODUCT
104 void IHOP_test() {
105 G1StaticIHOPControl::test();
106 }
107 #endif
|
33 _target_occupancy(target_occupancy) {
34 assert(_ihop_percent >= 0.0 && _ihop_percent <= 100.0, "Initial IHOP value must be between 0 and 100 but is %.3f", initial_ihop_percent);
35 }
36
37 G1StaticIHOPControl::G1StaticIHOPControl(double ihop_percent, size_t target_occupancy) :
38 G1IHOPControl(ihop_percent, target_occupancy),
39 _last_allocation_time_s(0.0),
40 _last_allocated_bytes(0),
41 _last_marking_length_s(0.0) {
42 assert(_target_occupancy > 0, "Target occupancy must be larger than zero.");
43 }
44
45 void G1StaticIHOPControl::print() {
46 ergo_verbose6(ErgoIHOP,
47 "basic information",
48 ergo_format_reason("value update")
49 ergo_format_byte_perc("threshold")
50 ergo_format_byte("target occupancy")
51 ergo_format_byte("current occupancy")
52 ergo_format_double("recent old gen allocation rate")
53 ergo_format_double("recent marking phase length"),
54 get_conc_mark_start_threshold(),
55 (double) get_conc_mark_start_threshold() / _target_occupancy * 100.0,
56 _target_occupancy,
57 G1CollectedHeap::heap()->used(),
58 _last_allocation_time_s > 0.0 ? _last_allocated_bytes / _last_allocation_time_s : 0.0,
59 _last_marking_length_s);
60 }
61
62 #ifndef PRODUCT
63 static void test_update(G1IHOPControl* ctrl, double alloc_time, size_t alloc_amount, size_t young_size, double mark_time) {
64 for (int i = 0; i < 100; i++) {
65 ctrl->update_allocation_info(alloc_time, alloc_amount, young_size);
66 ctrl->update_time_to_mixed(mark_time);
67 }
68 }
69
70 void G1StaticIHOPControl::test() {
71 size_t const initial_ihop = 45;
72
73 G1StaticIHOPControl ctrl(initial_ihop, 100);
74 size_t threshold;
75
76 threshold = ctrl.get_conc_mark_start_threshold();
77 assert(threshold == initial_ihop,
78 "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
79
83 "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
84
85 ctrl.update_time_to_mixed(1000.0);
86 threshold = ctrl.get_conc_mark_start_threshold();
87 assert(threshold == initial_ihop,
88 "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
89
90 // Whatever we pass, the IHOP value must stay the same.
91 test_update(&ctrl, 2, 10, 10, 3);
92 threshold = ctrl.get_conc_mark_start_threshold();
93 assert(threshold == initial_ihop,
94 "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
95
96 test_update(&ctrl, 12, 10, 10, 3);
97 threshold = ctrl.get_conc_mark_start_threshold();
98 assert(threshold == initial_ihop,
99 "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold);
100 }
101 #endif
102
103 G1AdaptiveIHOPControl::G1AdaptiveIHOPControl(double ihop_percent, size_t initial_target_occupancy, G1Predictions const* predictor) :
104 G1IHOPControl(ihop_percent, initial_target_occupancy),
105 _predictor(predictor),
106 _marking_times_s(10, 0.95),
107 _allocation_rate_s(10, 0.95),
108 _prev_unrestrained_young_size(0),
109 _current_threshold(0.0)
110 {
111 recalculate();
112 }
113
114 void G1AdaptiveIHOPControl::recalculate() {
115 if (have_enough_data_for_prediction()) {
116 double pred_marking_time = _predictor->get_new_prediction(&_marking_times_s);
117 double pred_promotion_rate = _predictor->get_new_prediction(&_allocation_rate_s);
118
119 size_t predicted_needed_bytes_during_marking =
120 (pred_marking_time * pred_promotion_rate +
121 _prev_unrestrained_young_size); // In reality we would need the size of the young gen of the first mixed GC. This is a conservative estimate.
122 size_t predicted_initiating_threshold = predicted_needed_bytes_during_marking < _target_occupancy ?
123 _target_occupancy - predicted_needed_bytes_during_marking :
124 0;
125 _current_threshold = predicted_initiating_threshold;
126 } else {
127 // Use the initial value.
128 _current_threshold = _ihop_percent * _target_occupancy / 100.0;
129 }
130 }
131
132 bool G1AdaptiveIHOPControl::have_enough_data_for_prediction() const {
133 return (_marking_times_s.num() > 2) && (_allocation_rate_s.num() > 2);
134 }
135
136 void G1AdaptiveIHOPControl::set_target_occupancy(size_t target_occupancy) {
137 _target_occupancy = target_occupancy;
138 }
139
140 size_t G1AdaptiveIHOPControl::get_conc_mark_start_threshold() {
141 recalculate();
142 return _current_threshold;
143 }
144
145 void G1AdaptiveIHOPControl::update_allocation_info(double allocation_time_s, size_t allocated_bytes, size_t additional_buffer_size) {
146 assert(allocation_time_s >= 0.0, "Allocation time must be positive but is %.3f", allocation_time_s);
147 double allocation_rate = (double) allocated_bytes / allocation_time_s;
148 _allocation_rate_s.add(allocation_rate);
149
150 _last_allocation_bytes = allocated_bytes;
151 _prev_unrestrained_young_size = additional_buffer_size;
152 }
153
154 void G1AdaptiveIHOPControl::update_time_to_mixed(double marking_length_s) {
155 assert(marking_length_s >= 0.0, "Marking length must be larger than zero but is %.3f", marking_length_s);
156 _marking_times_s.add(marking_length_s);
157 }
158
159 void G1AdaptiveIHOPControl::print() {
160 ergo_verbose6(ErgoIHOP,
161 "basic information",
162 ergo_format_reason("value update")
163 ergo_format_byte_perc("threshold")
164 ergo_format_byte("target occupancy")
165 ergo_format_byte("current occupancy")
166 ergo_format_double("recent old gen allocation rate")
167 ergo_format_double("recent marking phase length"),
168 get_conc_mark_start_threshold(),
169 _target_occupancy > 0 ? (double) get_conc_mark_start_threshold() / _target_occupancy * 100.0 : 0.0,
170 _target_occupancy,
171 G1CollectedHeap::heap()->used(),
172 _allocation_rate_s.last(),
173 _marking_times_s.last()
174 );
175 ergo_verbose3(ErgoIHOP,
176 "adaptive IHOP information",
177 ergo_format_reason("value update")
178 ergo_format_double("predicted old gen allocation rate")
179 ergo_format_double("predicted marking phase length")
180 ergo_format_str("prediction active"),
181 _predictor->get_new_prediction(&_allocation_rate_s),
182 _predictor->get_new_prediction(&_marking_times_s),
183 have_enough_data_for_prediction() ? "true" : "false"
184 );
185 }
186
187 #ifndef PRODUCT
188 void G1AdaptiveIHOPControl::test() {
189 size_t const initial_threshold = 45;
190 size_t const young_size = 10;
191 size_t const target_size = 100;
192
193 // The final IHOP value is always
194 // target_size - (young_size + alloc_amount/alloc_time * marking_time)
195
196 G1Predictions pred(0.95);
197 G1AdaptiveIHOPControl ctrl(initial_threshold, target_size, &pred);
198
199 // First "load".
200 size_t const alloc_time1 = 2;
201 size_t const alloc_amount1 = 10;
202 size_t const marking_time1 = 2;
203 size_t const settled_ihop1 = target_size - (young_size + alloc_amount1/alloc_time1 * marking_time1);
204
205 size_t threshold;
206 threshold = ctrl.get_conc_mark_start_threshold();
207 assert(threshold == initial_threshold,
208 "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_threshold, threshold);
209 ctrl.update_allocation_info(alloc_time1, alloc_amount1, young_size);
210 ctrl.update_time_to_mixed(marking_time1);
211 // Not enough data yet.
212 threshold = ctrl.get_conc_mark_start_threshold();
213 assert(threshold == initial_threshold,
214 "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_threshold, threshold);
215 // Not enough data yet.
216 ctrl.update_allocation_info(alloc_time1, alloc_amount1, young_size);
217 ctrl.update_time_to_mixed(marking_time1);
218 threshold = ctrl.get_conc_mark_start_threshold();
219 assert(threshold == initial_threshold,
220 "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_threshold, threshold);
221
222 test_update(&ctrl, alloc_time1, alloc_amount1, young_size, marking_time1);
223
224 threshold = ctrl.get_conc_mark_start_threshold();
225 assert(threshold == settled_ihop1,
226 "Expected IHOP threshold to settle at " SIZE_FORMAT " but is " SIZE_FORMAT, settled_ihop1, threshold);
227
228 // Second "load". A bit higher allocation rate.
229 size_t const alloc_time2 = 2;
230 size_t const alloc_amount2 = 30;
231 size_t const marking_time2 = 2;
232 size_t const settled_ihop2 = target_size - (young_size + alloc_amount2/alloc_time2 * marking_time2);
233
234 test_update(&ctrl, alloc_time2, alloc_amount2, young_size, marking_time2);
235
236 threshold = ctrl.get_conc_mark_start_threshold();
237 assert(threshold < settled_ihop1,
238 "Expected IHOP threshold to settle at a value lower than " SIZE_FORMAT " but is " SIZE_FORMAT, settled_ihop1, threshold);
239
240 // Third "load". Very high (impossible) allocation rate.
241 size_t const alloc_time3 = 1;
242 size_t const alloc_amount3 = 50;
243 size_t const marking_time3 = 2;
244 size_t const settled_ihop3 = 0; // target_size - (young_size + alloc_amount2/alloc_time2 * marking_time2);
245
246 test_update(&ctrl, alloc_time3, alloc_amount3, young_size, marking_time3);
247 threshold = ctrl.get_conc_mark_start_threshold();
248
249 assert(threshold == settled_ihop3,
250 "Expected IHOP threshold to settle at " SIZE_FORMAT " but is " SIZE_FORMAT, settled_ihop3, threshold);
251
252 // And back to some arbitrary value.
253 test_update(&ctrl, alloc_time2, alloc_amount2, young_size, marking_time2);
254
255 threshold = ctrl.get_conc_mark_start_threshold();
256 assert(threshold > settled_ihop3,
257 "Expected IHOP threshold to settle at value larger than " SIZE_FORMAT " but is " SIZE_FORMAT, settled_ihop3, threshold);
258 }
259
260 void IHOP_test() {
261 G1StaticIHOPControl::test();
262 G1AdaptiveIHOPControl::test();
263 }
264 #endif
|