| 1 | /* |
| 2 | * Copyright (c) 2016, 2019, Oracle and/or its affiliates. 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_G1_G1COLLECTIONSET_HPP |
| 26 | #define SHARE_GC_G1_G1COLLECTIONSET_HPP |
| 27 | |
| 28 | #include "utilities/debug.hpp" |
| 29 | #include "utilities/globalDefinitions.hpp" |
| 30 | |
| 31 | class G1CollectedHeap; |
| 32 | class G1CollectionSetCandidates; |
| 33 | class G1CollectorState; |
| 34 | class G1GCPhaseTimes; |
| 35 | class G1ParScanThreadStateSet; |
| 36 | class G1Policy; |
| 37 | class G1SurvivorRegions; |
| 38 | class HeapRegion; |
| 39 | class HeapRegionClosure; |
| 40 | |
| 41 | // The collection set. |
| 42 | // |
| 43 | // The set of regions that are evacuated during an evacuation pause. |
| 44 | // |
| 45 | // At the end of a collection, before freeing the collection set, this set |
| 46 | // contains all regions that were evacuated during this collection: |
| 47 | // |
| 48 | // - survivor regions from the last collection (if any) |
| 49 | // - eden regions allocated by the mutator |
| 50 | // - old gen regions evacuated during mixed gc |
| 51 | // |
| 52 | // This set is built incrementally at mutator time as regions are retired, and |
| 53 | // if this had been a mixed gc, some additional (during gc) incrementally added |
| 54 | // old regions from the collection set candidates built during the concurrent |
| 55 | // cycle. |
| 56 | // |
| 57 | // A more detailed overview of how the collection set changes over time follows: |
| 58 | // |
| 59 | // 0) at the end of GC the survivor regions are added to this collection set. |
| 60 | // 1) the mutator incrementally adds eden regions as they retire |
| 61 | // |
| 62 | // ----- gc starts |
| 63 | // |
| 64 | // 2) prepare (finalize) young regions of the collection set for collection |
| 65 | // - relabel the survivors as eden |
| 66 | // - finish up the incremental building that happened at mutator time |
| 67 | // |
| 68 | // iff this is a young-only collection: |
| 69 | // |
| 70 | // a3) evacuate the current collection set in one "initial evacuation" phase |
| 71 | // |
| 72 | // iff this is a mixed collection: |
| 73 | // |
| 74 | // b3) calculate the set of old gen regions we may be able to collect in this |
| 75 | // collection from the list of collection set candidates. |
| 76 | // - one part is added to the current collection set |
| 77 | // - the remainder regions are labeled as optional, and NOT yet added to the |
| 78 | // collection set. |
| 79 | // b4) evacuate the current collection set in the "initial evacuation" phase |
| 80 | // b5) evacuate the optional regions in the "optional evacuation" phase. This is |
| 81 | // done in increments (or rounds). |
| 82 | // b5-1) add a few of the optional regions to the current collection set |
| 83 | // b5-2) evacuate only these newly added optional regions. For this mechanism we |
| 84 | // reuse the incremental collection set building infrastructure (used also at |
| 85 | // mutator time). |
| 86 | // b5-3) repeat from b5-1 until the policy determines we are done |
| 87 | // |
| 88 | // all collections |
| 89 | // |
| 90 | // 6) free the collection set (contains all regions now; empties collection set |
| 91 | // afterwards) |
| 92 | // 7) add survivors to this collection set |
| 93 | // |
| 94 | // ----- gc ends |
| 95 | // |
| 96 | // goto 1) |
| 97 | // |
| 98 | // Examples of how the collection set might look over time: |
| 99 | // |
| 100 | // Legend: |
| 101 | // S = survivor, E = eden, O = old. |
| 102 | // |xxxx| = increment (with increment markers), containing four regions |
| 103 | // |
| 104 | // |SSSS| ... after step 0), with four survivor regions |
| 105 | // |SSSSEE| ... at step 1), after retiring two eden regions |
| 106 | // |SSSSEEEE| ... after step 1), after retiring four eden regions |
| 107 | // |EEEEEEEE| ... after step 2) |
| 108 | // |
| 109 | // iff this is a young-only collection |
| 110 | // |
| 111 | // EEEEEEEE|| ... after step a3), after initial evacuation phase |
| 112 | // || ... after step 6) |
| 113 | // |SS| ... after step 7), with two survivor regions |
| 114 | // |
| 115 | // iff this is a mixed collection |
| 116 | // |
| 117 | // |EEEEEEEEOOOO| ... after step b3), added four regions to be |
| 118 | // evacuated in the "initial evacuation" phase |
| 119 | // EEEEEEEEOOOO|| ... after step b4), incremental part is empty |
| 120 | // after evacuation |
| 121 | // EEEEEEEEOOOO|OO| ... after step b5.1), added two regions to be |
| 122 | // evacuated in the first round of the |
| 123 | // "optional evacuation" phase |
| 124 | // EEEEEEEEOOOOOO|O| ... after step b5.1), added one region to be |
| 125 | // evacuated in the second round of the |
| 126 | // "optional evacuation" phase |
| 127 | // EEEEEEEEOOOOOOO|| ... after step b5), the complete collection set. |
| 128 | // || ... after step b6) |
| 129 | // |SSS| ... after step 7), with three survivor regions |
| 130 | // |
| 131 | class G1CollectionSet { |
| 132 | G1CollectedHeap* _g1h; |
| 133 | G1Policy* _policy; |
| 134 | |
| 135 | // All old gen collection set candidate regions for the current mixed phase. |
| 136 | G1CollectionSetCandidates* _candidates; |
| 137 | |
| 138 | uint _eden_region_length; |
| 139 | uint _survivor_region_length; |
| 140 | uint _old_region_length; |
| 141 | |
| 142 | // The actual collection set as a set of region indices. |
| 143 | // All entries in _collection_set_regions below _collection_set_cur_length are |
| 144 | // assumed to be part of the collection set. |
| 145 | // We assume that at any time there is at most only one writer and (one or more) |
| 146 | // concurrent readers. This means we are good with using storestore and loadload |
| 147 | // barriers on the writer and reader respectively only. |
| 148 | uint* _collection_set_regions; |
| 149 | volatile size_t _collection_set_cur_length; |
| 150 | size_t _collection_set_max_length; |
| 151 | |
| 152 | // When doing mixed collections we can add old regions to the collection set, which |
| 153 | // will be collected only if there is enough time. We call these optional regions. |
| 154 | // This member records the current number of regions that are of that type that |
| 155 | // correspond to the first x entries in the collection set candidates. |
| 156 | uint _num_optional_regions; |
| 157 | |
| 158 | // The number of bytes in the collection set before the pause. Set from |
| 159 | // the incrementally built collection set at the start of an evacuation |
| 160 | // pause, and updated as more regions are added to the collection set. |
| 161 | size_t _bytes_used_before; |
| 162 | |
| 163 | // The number of cards in the remembered set in the collection set. Set from |
| 164 | // the incrementally built collection set at the start of an evacuation |
| 165 | // pause, and updated as more regions are added to the collection set. |
| 166 | size_t _recorded_rs_lengths; |
| 167 | |
| 168 | enum CSetBuildType { |
| 169 | Active, // We are actively building the collection set |
| 170 | Inactive // We are not actively building the collection set |
| 171 | }; |
| 172 | |
| 173 | CSetBuildType _inc_build_state; |
| 174 | size_t _inc_part_start; |
| 175 | |
| 176 | // The associated information that is maintained while the incremental |
| 177 | // collection set is being built with *young* regions. Used to populate |
| 178 | // the recorded info for the evacuation pause. |
| 179 | |
| 180 | // The number of bytes in the incrementally built collection set. |
| 181 | // Used to set _collection_set_bytes_used_before at the start of |
| 182 | // an evacuation pause. |
| 183 | size_t _inc_bytes_used_before; |
| 184 | |
| 185 | // The RSet lengths recorded for regions in the CSet. It is updated |
| 186 | // by the thread that adds a new region to the CSet. We assume that |
| 187 | // only one thread can be allocating a new CSet region (currently, |
| 188 | // it does so after taking the Heap_lock) hence no need to |
| 189 | // synchronize updates to this field. |
| 190 | size_t _inc_recorded_rs_lengths; |
| 191 | |
| 192 | // A concurrent refinement thread periodically samples the young |
| 193 | // region RSets and needs to update _inc_recorded_rs_lengths as |
| 194 | // the RSets grow. Instead of having to synchronize updates to that |
| 195 | // field we accumulate them in this field and add it to |
| 196 | // _inc_recorded_rs_lengths_diffs at the start of a GC. |
| 197 | ssize_t _inc_recorded_rs_lengths_diffs; |
| 198 | |
| 199 | // The predicted elapsed time it will take to collect the regions in |
| 200 | // the CSet. This is updated by the thread that adds a new region to |
| 201 | // the CSet. See the comment for _inc_recorded_rs_lengths about |
| 202 | // MT-safety assumptions. |
| 203 | double _inc_predicted_elapsed_time_ms; |
| 204 | |
| 205 | // See the comment for _inc_recorded_rs_lengths_diffs. |
| 206 | double _inc_predicted_elapsed_time_ms_diffs; |
| 207 | |
| 208 | void set_recorded_rs_lengths(size_t rs_lengths); |
| 209 | |
| 210 | G1CollectorState* collector_state(); |
| 211 | G1GCPhaseTimes* phase_times(); |
| 212 | |
| 213 | void verify_young_cset_indices() const NOT_DEBUG_RETURN; |
| 214 | |
| 215 | double predict_region_elapsed_time_ms(HeapRegion* hr); |
| 216 | |
| 217 | // Update the incremental collection set information when adding a region. |
| 218 | void add_young_region_common(HeapRegion* hr); |
| 219 | |
| 220 | // Add old region "hr" to the collection set. |
| 221 | void add_old_region(HeapRegion* hr); |
| 222 | void free_optional_regions(); |
| 223 | |
| 224 | // Add old region "hr" to optional collection set. |
| 225 | void add_optional_region(HeapRegion* hr); |
| 226 | |
| 227 | void move_candidates_to_collection_set(uint num_regions); |
| 228 | |
| 229 | // Finalize the young part of the initial collection set. Relabel survivor regions |
| 230 | // as Eden and calculate a prediction on how long the evacuation of all young regions |
| 231 | // will take. |
| 232 | double finalize_young_part(double target_pause_time_ms, G1SurvivorRegions* survivors); |
| 233 | // Perform any final calculations on the incremental collection set fields before we |
| 234 | // can use them. |
| 235 | void finalize_incremental_building(); |
| 236 | |
| 237 | // Select the old regions of the initial collection set and determine how many optional |
| 238 | // regions we might be able to evacuate in this pause. |
| 239 | void finalize_old_part(double time_remaining_ms); |
| 240 | public: |
| 241 | G1CollectionSet(G1CollectedHeap* g1h, G1Policy* policy); |
| 242 | ~G1CollectionSet(); |
| 243 | |
| 244 | // Initializes the collection set giving the maximum possible length of the collection set. |
| 245 | void initialize(uint max_region_length); |
| 246 | |
| 247 | void clear_candidates(); |
| 248 | |
| 249 | void set_candidates(G1CollectionSetCandidates* candidates) { |
| 250 | assert(_candidates == NULL, "Trying to replace collection set candidates." ); |
| 251 | _candidates = candidates; |
| 252 | } |
| 253 | G1CollectionSetCandidates* candidates() { return _candidates; } |
| 254 | |
| 255 | void init_region_lengths(uint eden_cset_region_length, |
| 256 | uint survivor_cset_region_length); |
| 257 | |
| 258 | uint region_length() const { return young_region_length() + |
| 259 | old_region_length(); } |
| 260 | uint young_region_length() const { return eden_region_length() + |
| 261 | survivor_region_length(); } |
| 262 | |
| 263 | uint eden_region_length() const { return _eden_region_length; } |
| 264 | uint survivor_region_length() const { return _survivor_region_length; } |
| 265 | uint old_region_length() const { return _old_region_length; } |
| 266 | uint optional_region_length() const { return _num_optional_regions; } |
| 267 | |
| 268 | // Reset the contents of the collection set. |
| 269 | void clear(); |
| 270 | |
| 271 | // Incremental collection set support |
| 272 | |
| 273 | // Initialize incremental collection set info. |
| 274 | void start_incremental_building(); |
| 275 | // Start a new collection set increment. |
| 276 | void update_incremental_marker() { _inc_build_state = Active; _inc_part_start = _collection_set_cur_length; } |
| 277 | // Stop adding regions to the current collection set increment. |
| 278 | void stop_incremental_building() { _inc_build_state = Inactive; } |
| 279 | |
| 280 | // Iterate over the current collection set increment applying the given HeapRegionClosure |
| 281 | // from a starting position determined by the given worker id. |
| 282 | void iterate_incremental_part_from(HeapRegionClosure* cl, uint worker_id, uint total_workers) const; |
| 283 | |
| 284 | // Iterate over the entire collection set (all increments calculated so far), applying |
| 285 | // the given HeapRegionClosure on all of them. |
| 286 | void iterate(HeapRegionClosure* cl) const; |
| 287 | |
| 288 | void iterate_optional(HeapRegionClosure* cl) const; |
| 289 | |
| 290 | size_t recorded_rs_lengths() { return _recorded_rs_lengths; } |
| 291 | |
| 292 | size_t bytes_used_before() const { |
| 293 | return _bytes_used_before; |
| 294 | } |
| 295 | |
| 296 | void reset_bytes_used_before() { |
| 297 | _bytes_used_before = 0; |
| 298 | } |
| 299 | |
| 300 | // Finalize the initial collection set consisting of all young regions potentially a |
| 301 | // few old gen regions. |
| 302 | void finalize_initial_collection_set(double target_pause_time_ms, G1SurvivorRegions* survivor); |
| 303 | // Finalize the next collection set from the set of available optional old gen regions. |
| 304 | bool finalize_optional_for_evacuation(double remaining_pause_time); |
| 305 | // Abandon (clean up) optional collection set regions that were not evacuated in this |
| 306 | // pause. |
| 307 | void abandon_optional_collection_set(G1ParScanThreadStateSet* pss); |
| 308 | |
| 309 | // Update information about hr in the aggregated information for |
| 310 | // the incrementally built collection set. |
| 311 | void update_young_region_prediction(HeapRegion* hr, size_t new_rs_length); |
| 312 | |
| 313 | // Add eden region to the collection set. |
| 314 | void add_eden_region(HeapRegion* hr); |
| 315 | |
| 316 | // Add survivor region to the collection set. |
| 317 | void add_survivor_regions(HeapRegion* hr); |
| 318 | |
| 319 | #ifndef PRODUCT |
| 320 | bool verify_young_ages(); |
| 321 | |
| 322 | void print(outputStream* st); |
| 323 | #endif // !PRODUCT |
| 324 | }; |
| 325 | |
| 326 | #endif // SHARE_GC_G1_G1COLLECTIONSET_HPP |
| 327 | |