33
34 G1HeapSizingPolicy* G1HeapSizingPolicy::create(const G1CollectedHeap* g1h, const G1Analytics* analytics) {
35 return new G1HeapSizingPolicy(g1h, analytics);
36 }
37
38 G1HeapSizingPolicy::G1HeapSizingPolicy(const G1CollectedHeap* g1h, const G1Analytics* analytics) :
39 _g1h(g1h),
40 _analytics(analytics),
41 _num_prev_pauses_for_heuristics(analytics->number_of_recorded_pause_times()) {
42
43 assert(MinOverThresholdForGrowth < _num_prev_pauses_for_heuristics, "Threshold must be less than %u", _num_prev_pauses_for_heuristics);
44 clear_ratio_check_data();
45 }
46
47 void G1HeapSizingPolicy::clear_ratio_check_data() {
48 _ratio_over_threshold_count = 0;
49 _ratio_over_threshold_sum = 0.0;
50 _pauses_since_start = 0;
51 }
52
53 size_t G1HeapSizingPolicy::expansion_amount() {
54 assert(GCTimeRatio > 0,
55 "we should have set it to a default value set_g1_gc_flags() "
56 "if a user set it to 0");
57
58 double long_term_gc_overhead = _analytics->long_term_pause_time_ratio() * 100.0;
59 double short_term_gc_overhead = _analytics->short_term_pause_time_ratio() * 100.0;
60 size_t expand_bytes = 0;
61
62 if (_g1h->capacity() == _g1h->max_capacity()) {
63 log_trace(gc, ergo, heap)("Can not expand (heap already fully expanded) "
64 "long term GC overhead: %1.2f %% committed: " SIZE_FORMAT "B",
65 long_term_gc_overhead, _g1h->capacity());
66
67 clear_ratio_check_data();
68 return expand_bytes;
69 }
70
71 const double gc_overhead_percent = 100.0 * (1.0 / (1.0 + GCTimeRatio));
72
73 double threshold = gc_overhead_percent;
74
75 // If the heap is at less than half its maximum size, scale the threshold down,
76 // to a limit of 1. Thus the smaller the heap is, the more likely it is to expand,
77 // though the scaling code will likely keep the increase small.
78 if (_g1h->capacity() <= _g1h->max_capacity() / 2) {
79 threshold *= (double)_g1h->capacity() / (double)(_g1h->max_capacity() / 2);
80 threshold = MAX2(threshold, 1.0);
81 }
82
83 // If the last GC time ratio is over the threshold, increment the count of
84 // times it has been exceeded, and add this ratio to the sum of exceeded
85 // ratios.
86 if (short_term_gc_overhead > threshold) {
87 _ratio_over_threshold_count++;
88 _ratio_over_threshold_sum += short_term_gc_overhead;
89 }
90
91 // Check if we've had enough GC time ratio checks that were over the
92 // threshold to trigger an expansion. We'll also expand if we've
93 // reached the end of the history buffer and the average of all entries
94 // is still over the threshold. This indicates a smaller number of GCs were
95 // long enough to make the average exceed the threshold.
96 bool filled_history_buffer = _pauses_since_start == _num_prev_pauses_for_heuristics;
97 if ((_ratio_over_threshold_count == MinOverThresholdForGrowth) ||
98 (filled_history_buffer && (long_term_gc_overhead > threshold))) {
99 size_t min_expand_bytes = HeapRegion::GrainBytes;
100 size_t reserved_bytes = _g1h->max_capacity();
101 size_t committed_bytes = _g1h->capacity();
102 size_t uncommitted_bytes = reserved_bytes - committed_bytes;
103 size_t expand_bytes_via_pct =
104 uncommitted_bytes * G1ExpandByPercentOfAvailable / 100;
105 double scale_factor = 1.0;
106
107 // If the current size is less than 1/4 of the Initial heap size, expand
108 // by half of the delta between the current and Initial sizes. IE, grow
109 // back quickly.
110 //
111 // Otherwise, take the current size, or G1ExpandByPercentOfAvailable % of
112 // the available expansion space, whichever is smaller, as the base
113 // expansion size. Then possibly scale this size according to how much the
114 // threshold has (on average) been exceeded by. If the delta is small
115 // (less than the StartScaleDownAt value), scale the size down linearly, but
116 // not by less than MinScaleDownFactor. If the delta is large (greater than
117 // the StartScaleUpAt value), scale up, but adding no more than MaxScaleUpFactor
118 // times the base size. The scaling will be linear in the range from
119 // StartScaleUpAt to (StartScaleUpAt + ScaleUpRange). In other words,
120 // ScaleUpRange sets the rate of scaling up.
121 if (committed_bytes < InitialHeapSize / 4) {
122 expand_bytes = (InitialHeapSize - committed_bytes) / 2;
123 } else {
124 double const MinScaleDownFactor = 0.2;
125 double const MaxScaleUpFactor = 2;
126 double const StartScaleDownAt = gc_overhead_percent;
127 double const StartScaleUpAt = gc_overhead_percent * 1.5;
128 double const ScaleUpRange = gc_overhead_percent * 2.0;
129
130 double ratio_delta;
131 if (filled_history_buffer) {
132 ratio_delta = long_term_gc_overhead - threshold;
133 } else {
134 ratio_delta = (_ratio_over_threshold_sum/_ratio_over_threshold_count) - threshold;
135 }
136
137 expand_bytes = MIN2(expand_bytes_via_pct, committed_bytes);
138 if (ratio_delta < StartScaleDownAt) {
139 scale_factor = ratio_delta / StartScaleDownAt;
140 scale_factor = MAX2(scale_factor, MinScaleDownFactor);
141 } else if (ratio_delta > StartScaleUpAt) {
142 scale_factor = 1 + ((ratio_delta - StartScaleUpAt) / ScaleUpRange);
143 scale_factor = MIN2(scale_factor, MaxScaleUpFactor);
144 }
145 }
146
147 log_debug(gc, ergo, heap)("Attempt heap expansion (recent GC overhead higher than threshold after GC) "
148 "long term GC overhead: %1.2f %% threshold: %1.2f %% uncommitted: " SIZE_FORMAT "B base expansion amount and scale: " SIZE_FORMAT "B (%1.2f%%)",
149 long_term_gc_overhead, threshold, uncommitted_bytes, expand_bytes, scale_factor * 100);
150
151 expand_bytes = static_cast<size_t>(expand_bytes * scale_factor);
152
153 // Ensure the expansion size is at least the minimum growth amount
154 // and at most the remaining uncommitted byte size.
155 expand_bytes = MAX2(expand_bytes, min_expand_bytes);
156 expand_bytes = MIN2(expand_bytes, uncommitted_bytes);
157
158 clear_ratio_check_data();
159 } else {
160 // An expansion was not triggered. If we've started counting, increment
161 // the number of checks we've made in the current window. If we've
162 // reached the end of the window without resizing, clear the counters to
163 // start again the next time we see a ratio above the threshold.
164 if (_ratio_over_threshold_count > 0) {
165 _pauses_since_start++;
166 if (_pauses_since_start > _num_prev_pauses_for_heuristics) {
167 clear_ratio_check_data();
168 }
169 }
|
33
34 G1HeapSizingPolicy* G1HeapSizingPolicy::create(const G1CollectedHeap* g1h, const G1Analytics* analytics) {
35 return new G1HeapSizingPolicy(g1h, analytics);
36 }
37
38 G1HeapSizingPolicy::G1HeapSizingPolicy(const G1CollectedHeap* g1h, const G1Analytics* analytics) :
39 _g1h(g1h),
40 _analytics(analytics),
41 _num_prev_pauses_for_heuristics(analytics->number_of_recorded_pause_times()) {
42
43 assert(MinOverThresholdForGrowth < _num_prev_pauses_for_heuristics, "Threshold must be less than %u", _num_prev_pauses_for_heuristics);
44 clear_ratio_check_data();
45 }
46
47 void G1HeapSizingPolicy::clear_ratio_check_data() {
48 _ratio_over_threshold_count = 0;
49 _ratio_over_threshold_sum = 0.0;
50 _pauses_since_start = 0;
51 }
52
53 double G1HeapSizingPolicy::scale_with_heap(double pause_time_ratio) {
54 double threshold = pause_time_ratio;
55 // If the heap is at less than half its maximum size, scale the threshold down,
56 // to a limit of 1%. Thus the smaller the heap is, the more likely it is to expand,
57 // though the scaling code will likely keep the increase small.
58 if (_g1h->capacity() <= _g1h->max_capacity() / 2) {
59 threshold *= (double)_g1h->capacity() / (double)(_g1h->max_capacity() / 2);
60 threshold = MAX2(threshold, 0.01);
61 }
62
63 return threshold;
64 }
65
66 size_t G1HeapSizingPolicy::expansion_amount() {
67 assert(GCTimeRatio > 0, "must be");
68
69 double long_term_pause_time_ratio = _analytics->long_term_pause_time_ratio();
70 double short_term_pause_time_ratio = _analytics->short_term_pause_time_ratio();
71 size_t expand_bytes = 0;
72
73 if (_g1h->capacity() == _g1h->max_capacity()) {
74 log_trace(gc, ergo, heap)("Can not expand (heap already fully expanded) "
75 "long term GC overhead: %1.2f%% committed: " SIZE_FORMAT "B",
76 long_term_pause_time_ratio * 100.0, _g1h->capacity());
77
78 clear_ratio_check_data();
79 return expand_bytes;
80 }
81
82 const double pause_time_ratio = 1.0 / (1.0 + GCTimeRatio);
83
84 double threshold = scale_with_heap(pause_time_ratio);
85
86 // If the last GC time ratio is over the threshold, increment the count of
87 // times it has been exceeded, and add this ratio to the sum of exceeded
88 // ratios.
89 if (short_term_pause_time_ratio > threshold) {
90 _ratio_over_threshold_count++;
91 _ratio_over_threshold_sum += short_term_pause_time_ratio;
92 }
93 // Check if we've had enough GC time ratio checks that were over the
94 // threshold to trigger an expansion. We'll also expand if we've
95 // reached the end of the history buffer and the average of all entries
96 // is still over the threshold. This indicates a smaller number of GCs were
97 // long enough to make the average exceed the threshold.
98 bool filled_history_buffer = _pauses_since_start == _num_prev_pauses_for_heuristics;
99 if ((_ratio_over_threshold_count == MinOverThresholdForGrowth) ||
100 (filled_history_buffer && (long_term_pause_time_ratio > threshold))) {
101 size_t min_expand_bytes = HeapRegion::GrainBytes;
102 size_t reserved_bytes = _g1h->max_capacity();
103 size_t committed_bytes = _g1h->capacity();
104 size_t uncommitted_bytes = reserved_bytes - committed_bytes;
105 size_t expand_bytes_via_pct =
106 uncommitted_bytes * G1ExpandByPercentOfAvailable / 100;
107 double scale_factor = 1.0;
108
109 // If the current size is less than 1/4 of the Initial heap size, expand
110 // by half of the delta between the current and Initial sizes. IE, grow
111 // back quickly.
112 //
113 // Otherwise, take the current size, or G1ExpandByPercentOfAvailable % of
114 // the available expansion space, whichever is smaller, as the base
115 // expansion size. Then possibly scale this size according to how much the
116 // threshold has (on average) been exceeded by. If the delta is small
117 // (less than the StartScaleDownAt value), scale the size down linearly, but
118 // not by less than MinScaleDownFactor. If the delta is large (greater than
119 // the StartScaleUpAt value), scale up, but adding no more than MaxScaleUpFactor
120 // times the base size. The scaling will be linear in the range from
121 // StartScaleUpAt to (StartScaleUpAt + ScaleUpRange). In other words,
122 // ScaleUpRange sets the rate of scaling up.
123 if (committed_bytes < InitialHeapSize / 4) {
124 expand_bytes = (InitialHeapSize - committed_bytes) / 2;
125 } else {
126 double const MinScaleDownFactor = 0.2;
127 double const MaxScaleUpFactor = 2;
128 double const StartScaleDownAt = pause_time_ratio;
129 double const StartScaleUpAt = pause_time_ratio * 1.5;
130 double const ScaleUpRange = pause_time_ratio * 2.0;
131
132 double ratio_delta;
133 if (filled_history_buffer) {
134 ratio_delta = long_term_pause_time_ratio - threshold;
135 } else {
136 ratio_delta = (_ratio_over_threshold_sum / _ratio_over_threshold_count) - threshold;
137 }
138
139 expand_bytes = MIN2(expand_bytes_via_pct, committed_bytes);
140 if (ratio_delta < StartScaleDownAt) {
141 scale_factor = ratio_delta / StartScaleDownAt;
142 scale_factor = MAX2(scale_factor, MinScaleDownFactor);
143 } else if (ratio_delta > StartScaleUpAt) {
144 scale_factor = 1 + ((ratio_delta - StartScaleUpAt) / ScaleUpRange);
145 scale_factor = MIN2(scale_factor, MaxScaleUpFactor);
146 }
147 }
148
149 log_debug(gc, ergo, heap)("Attempt heap expansion (recent GC overhead higher than threshold after GC) "
150 "long term GC overhead: %1.2f%% threshold: %1.2f%% uncommitted: " SIZE_FORMAT "B "
151 "base expansion amount and scale: " SIZE_FORMAT "B (%1.2f%%)",
152 long_term_pause_time_ratio * 100.0, threshold * 100.0,
153 uncommitted_bytes, expand_bytes, scale_factor * 100.0);
154
155 expand_bytes = static_cast<size_t>(expand_bytes * scale_factor);
156
157 // Ensure the expansion size is at least the minimum growth amount
158 // and at most the remaining uncommitted byte size.
159 expand_bytes = MAX2(expand_bytes, min_expand_bytes);
160 expand_bytes = MIN2(expand_bytes, uncommitted_bytes);
161
162 clear_ratio_check_data();
163 } else {
164 // An expansion was not triggered. If we've started counting, increment
165 // the number of checks we've made in the current window. If we've
166 // reached the end of the window without resizing, clear the counters to
167 // start again the next time we see a ratio above the threshold.
168 if (_ratio_over_threshold_count > 0) {
169 _pauses_since_start++;
170 if (_pauses_since_start > _num_prev_pauses_for_heuristics) {
171 clear_ratio_check_data();
172 }
173 }
|