64 size_t capacity = ShenandoahHeap::heap()->max_capacity(); |
64 size_t capacity = ShenandoahHeap::heap()->max_capacity(); |
65 size_t free_target = capacity / 100 * ShenandoahMinFreeThreshold; |
65 size_t free_target = capacity / 100 * ShenandoahMinFreeThreshold; |
66 size_t min_garbage = free_target > actual_free ? (free_target - actual_free) : 0; |
66 size_t min_garbage = free_target > actual_free ? (free_target - actual_free) : 0; |
67 size_t max_cset = (size_t)((1.0 * capacity / 100 * ShenandoahEvacReserve) / ShenandoahEvacWaste); |
67 size_t max_cset = (size_t)((1.0 * capacity / 100 * ShenandoahEvacReserve) / ShenandoahEvacWaste); |
68 |
68 |
69 log_info(gc, ergo)("Adaptive CSet Selection. Target Free: " SIZE_FORMAT "M, Actual Free: " |
69 log_info(gc, ergo)("Adaptive CSet Selection. Target Free: " SIZE_FORMAT "%s, Actual Free: " |
70 SIZE_FORMAT "M, Max CSet: " SIZE_FORMAT "M, Min Garbage: " SIZE_FORMAT "M", |
70 SIZE_FORMAT "%s, Max CSet: " SIZE_FORMAT "%s, Min Garbage: " SIZE_FORMAT "%s", |
71 free_target / M, actual_free / M, max_cset / M, min_garbage / M); |
71 byte_size_in_proper_unit(free_target), proper_unit_for_byte_size(free_target), |
|
72 byte_size_in_proper_unit(actual_free), proper_unit_for_byte_size(actual_free), |
|
73 byte_size_in_proper_unit(max_cset), proper_unit_for_byte_size(max_cset), |
|
74 byte_size_in_proper_unit(min_garbage), proper_unit_for_byte_size(min_garbage)); |
72 |
75 |
73 // Better select garbage-first regions |
76 // Better select garbage-first regions |
74 QuickSort::sort<RegionData>(data, (int)size, compare_by_garbage, false); |
77 QuickSort::sort<RegionData>(data, (int)size, compare_by_garbage, false); |
75 |
78 |
76 size_t cur_cset = 0; |
79 size_t cur_cset = 0; |
117 |
120 |
118 // Check if we are falling below the worst limit, time to trigger the GC, regardless of |
121 // Check if we are falling below the worst limit, time to trigger the GC, regardless of |
119 // anything else. |
122 // anything else. |
120 size_t min_threshold = capacity / 100 * ShenandoahMinFreeThreshold; |
123 size_t min_threshold = capacity / 100 * ShenandoahMinFreeThreshold; |
121 if (available < min_threshold) { |
124 if (available < min_threshold) { |
122 log_info(gc)("Trigger: Free (" SIZE_FORMAT "M) is below minimum threshold (" SIZE_FORMAT "M)", |
125 log_info(gc)("Trigger: Free (" SIZE_FORMAT "%s) is below minimum threshold (" SIZE_FORMAT "%s)", |
123 available / M, min_threshold / M); |
126 byte_size_in_proper_unit(available), proper_unit_for_byte_size(available), |
|
127 byte_size_in_proper_unit(min_threshold), proper_unit_for_byte_size(min_threshold)); |
124 return true; |
128 return true; |
125 } |
129 } |
126 |
130 |
127 // Check if are need to learn a bit about the application |
131 // Check if are need to learn a bit about the application |
128 const size_t max_learn = ShenandoahLearningSteps; |
132 const size_t max_learn = ShenandoahLearningSteps; |
129 if (_gc_times_learned < max_learn) { |
133 if (_gc_times_learned < max_learn) { |
130 size_t init_threshold = capacity / 100 * ShenandoahInitFreeThreshold; |
134 size_t init_threshold = capacity / 100 * ShenandoahInitFreeThreshold; |
131 if (available < init_threshold) { |
135 if (available < init_threshold) { |
132 log_info(gc)("Trigger: Learning " SIZE_FORMAT " of " SIZE_FORMAT ". Free (" SIZE_FORMAT "M) is below initial threshold (" SIZE_FORMAT "M)", |
136 log_info(gc)("Trigger: Learning " SIZE_FORMAT " of " SIZE_FORMAT ". Free (" SIZE_FORMAT "%s) is below initial threshold (" SIZE_FORMAT "%s)", |
133 _gc_times_learned + 1, max_learn, available / M, init_threshold / M); |
137 _gc_times_learned + 1, max_learn, |
|
138 byte_size_in_proper_unit(available), proper_unit_for_byte_size(available), |
|
139 byte_size_in_proper_unit(init_threshold), proper_unit_for_byte_size(init_threshold)); |
134 return true; |
140 return true; |
135 } |
141 } |
136 } |
142 } |
137 |
143 |
138 // Check if allocation headroom is still okay. This also factors in: |
144 // Check if allocation headroom is still okay. This also factors in: |
152 double average_gc = _gc_time_history->avg(); |
158 double average_gc = _gc_time_history->avg(); |
153 double time_since_last = time_since_last_gc(); |
159 double time_since_last = time_since_last_gc(); |
154 double allocation_rate = heap->bytes_allocated_since_gc_start() / time_since_last; |
160 double allocation_rate = heap->bytes_allocated_since_gc_start() / time_since_last; |
155 |
161 |
156 if (average_gc > allocation_headroom / allocation_rate) { |
162 if (average_gc > allocation_headroom / allocation_rate) { |
157 log_info(gc)("Trigger: Average GC time (%.2f ms) is above the time for allocation rate (%.2f MB/s) to deplete free headroom (" SIZE_FORMAT "M)", |
163 log_info(gc)("Trigger: Average GC time (%.2f ms) is above the time for allocation rate (%.0f %sB/s) to deplete free headroom (" SIZE_FORMAT "%s)", |
158 average_gc * 1000, allocation_rate / M, allocation_headroom / M); |
164 average_gc * 1000, |
159 log_info(gc, ergo)("Free headroom: " SIZE_FORMAT "M (free) - " SIZE_FORMAT "M (spike) - " SIZE_FORMAT "M (penalties) = " SIZE_FORMAT "M", |
165 byte_size_in_proper_unit(allocation_rate), proper_unit_for_byte_size(allocation_rate), |
160 available / M, spike_headroom / M, penalties / M, allocation_headroom / M); |
166 byte_size_in_proper_unit(allocation_headroom), proper_unit_for_byte_size(allocation_headroom)); |
|
167 log_info(gc, ergo)("Free headroom: " SIZE_FORMAT "%s (free) - " SIZE_FORMAT "%s (spike) - " SIZE_FORMAT "%s (penalties) = " SIZE_FORMAT "%s", |
|
168 byte_size_in_proper_unit(available), proper_unit_for_byte_size(available), |
|
169 byte_size_in_proper_unit(spike_headroom), proper_unit_for_byte_size(spike_headroom), |
|
170 byte_size_in_proper_unit(penalties), proper_unit_for_byte_size(penalties), |
|
171 byte_size_in_proper_unit(allocation_headroom), proper_unit_for_byte_size(allocation_headroom)); |
161 return true; |
172 return true; |
162 } |
173 } |
163 |
174 |
164 return ShenandoahHeuristics::should_start_gc(); |
175 return ShenandoahHeuristics::should_start_gc(); |
165 } |
176 } |