--- old/src/hotspot/share/gc/g1/g1CollectionSetCandidates.cpp 2019-01-25 14:26:55.342094108 +0100 +++ new/src/hotspot/share/gc/g1/g1CollectionSetCandidates.cpp 2019-01-25 14:26:54.852078997 +0100 @@ -23,8 +23,8 @@ */ #include "precompiled.hpp" -#include "gc/g1/collectionSetChooser.hpp" #include "gc/g1/g1CollectionSetCandidates.hpp" +#include "gc/g1/g1CollectionSetChooser.hpp" #include "gc/g1/heapRegion.inline.hpp" HeapRegion* G1CollectionSetCandidates::pop_front() { @@ -73,7 +73,7 @@ for (; idx < _num_regions; idx++) { HeapRegion *cur = _regions[idx]; guarantee(cur != NULL, "Regions after _front_idx %u cannot be NULL but %u is", _front_idx, idx); - guarantee(CollectionSetChooser::should_add(cur), "Region %u should be eligible for addition.", cur->hrm_index()); + guarantee(G1CollectionSetChooser::should_add(cur), "Region %u should be eligible for addition.", cur->hrm_index()); if (prev != NULL) { guarantee(prev->gc_efficiency() >= cur->gc_efficiency(), "GC efficiency for region %u: %1.4f smaller than for region %u: %1.4f", --- old/src/hotspot/share/gc/g1/g1Policy.cpp 2019-01-25 14:26:57.144149677 +0100 +++ new/src/hotspot/share/gc/g1/g1Policy.cpp 2019-01-25 14:26:56.655134598 +0100 @@ -23,10 +23,10 @@ */ #include "precompiled.hpp" -#include "gc/g1/collectionSetChooser.hpp" #include "gc/g1/g1Analytics.hpp" #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectionSet.hpp" +#include "gc/g1/g1CollectionSetChooser.hpp" #include "gc/g1/g1ConcurrentMark.hpp" #include "gc/g1/g1ConcurrentMarkThread.inline.hpp" #include "gc/g1/g1ConcurrentRefine.hpp" @@ -1027,7 +1027,7 @@ } void G1Policy::record_concurrent_mark_cleanup_end() { - G1CollectionSetCandidates* candidates = CollectionSetChooser::build(_g1h->workers(), _g1h->num_regions()); + G1CollectionSetCandidates* candidates = G1CollectionSetChooser::build(_g1h->workers(), _g1h->num_regions()); _collection_set->set_candidates(candidates); bool mixed_gc_pending = next_gc_should_be_mixed("request mixed gcs", "request young-only gcs"); --- old/src/hotspot/share/gc/g1/g1Policy.hpp 2019-01-25 14:26:58.948205308 +0100 +++ new/src/hotspot/share/gc/g1/g1Policy.hpp 2019-01-25 14:26:58.461190290 +0100 @@ -44,7 +44,7 @@ class HeapRegion; class G1CollectionSet; -class CollectionSetChooser; +class G1CollectionSetChooser; class G1IHOPControl; class G1Analytics; class G1SurvivorRegions; @@ -176,7 +176,7 @@ double non_young_other_time_ms() const; double constant_other_time_ms(double pause_time_ms) const; - CollectionSetChooser* cset_chooser() const; + G1CollectionSetChooser* cset_chooser() const; // The number of bytes copied during the GC. size_t _bytes_copied_during_gc; --- old/src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.cpp 2019-01-25 14:27:00.748260816 +0100 +++ new/src/hotspot/share/gc/g1/g1RemSetTrackingPolicy.cpp 2019-01-25 14:27:00.260245767 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "gc/g1/collectionSetChooser.hpp" +#include "gc/g1/g1CollectionSetChooser.hpp" #include "gc/g1/g1RemSetTrackingPolicy.hpp" #include "gc/g1/heapRegion.inline.hpp" #include "gc/g1/heapRegionRemSet.hpp" @@ -126,7 +126,7 @@ // - Otherwise only add those old gen regions which occupancy is low enough that there // is a chance that we will ever evacuate them in the mixed gcs. if ((total_live_bytes > 0) && - CollectionSetChooser::region_occupancy_low_enough_for_evac(total_live_bytes) && + G1CollectionSetChooser::region_occupancy_low_enough_for_evac(total_live_bytes) && !r->rem_set()->is_tracked()) { r->rem_set()->set_state_updating(); --- old/src/hotspot/share/gc/g1/collectionSetChooser.cpp 2019-01-25 14:27:02.608318174 +0100 +++ /dev/null 2019-01-25 10:20:53.925519614 +0100 @@ -1,269 +0,0 @@ -/* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "gc/g1/collectionSetChooser.hpp" -#include "gc/g1/g1CollectedHeap.inline.hpp" -#include "gc/g1/heapRegionRemSet.hpp" -#include "gc/shared/space.inline.hpp" -#include "runtime/atomic.hpp" -#include "utilities/quickSort.hpp" - -// Order regions according to GC efficiency. This will cause regions with a lot -// of live objects and large remembered sets to end up at the end of the array. -// Given that we might skip collecting the last few old regions, if after a few -// mixed GCs the remaining have reclaimable bytes under a certain threshold, the -// hope is that the ones we'll skip are ones with both large remembered sets and -// a lot of live objects, not the ones with just a lot of live objects if we -// ordered according to the amount of reclaimable bytes per region. -static int order_regions(HeapRegion* hr1, HeapRegion* hr2) { - // Make sure that NULL entries are moved to the end. - if (hr1 == NULL) { - if (hr2 == NULL) { - return 0; - } else { - return 1; - } - } else if (hr2 == NULL) { - return -1; - } - - double gc_eff1 = hr1->gc_efficiency(); - double gc_eff2 = hr2->gc_efficiency(); - - if (gc_eff1 > gc_eff2) { - return -1; - } if (gc_eff1 < gc_eff2) { - return 1; - } else { - return 0; - } -} - -// Determine collection set candidates: For all regions determine whether they -// should be a collection set candidates, calculate their efficiency, sort and -// return them as G1CollectionSetCandidates instance. -// Threads calculate the GC efficiency of the regions they get to process, and -// put them into some work area unsorted. At the end the array is sorted and -// copied into the G1CollectionSetCandidates instance; the caller will be the new -// owner of this object. -class G1BuildCandidateRegionsTask : public AbstractGangTask { - - // Work area for building the set of collection set candidates. Contains references - // to heap regions with their GC efficiencies calculated. To reduce contention - // on claiming array elements, worker threads claim parts of this array in chunks; - // Array elements may be NULL as threads might not get enough regions to fill - // up their chunks completely. - // Final sorting will remove them. - class G1BuildCandidateArray : public StackObj { - - uint const _max_size; - uint const _chunk_size; - - HeapRegion** _data; - - uint volatile _cur_claim_idx; - - // Calculates the maximum array size that will be used. - static uint required_array_size(uint num_regions, uint num_workers, uint chunk_size) { - uint const max_waste = num_workers * chunk_size; - // The array should be aligned with respect to chunk_size. - uint const aligned_num_regions = ((num_regions + chunk_size - 1) / chunk_size) * chunk_size; - - return aligned_num_regions + max_waste; - } - - public: - G1BuildCandidateArray(uint max_num_regions, uint num_workers, uint chunk_size) : - _max_size(required_array_size(max_num_regions, num_workers, chunk_size)), - _chunk_size(chunk_size), - _data(NEW_C_HEAP_ARRAY(HeapRegion*, _max_size, mtGC)), - _cur_claim_idx(0) { - for (uint i = 0; i < _max_size; i++) { - _data[i] = NULL; - } - } - - ~G1BuildCandidateArray() { - FREE_C_HEAP_ARRAY(HeapRegion*, _data); - } - - // Claim a new chunk, returning its bounds [from, to[. - void claim_chunk(uint& from, uint& to) { - uint result = Atomic::add(_chunk_size, &_cur_claim_idx); - assert(_max_size > result - 1, - "Array too small, is %u should be %u with chunk size %u.", - _max_size, result, _chunk_size); - from = result - _chunk_size; - to = result; - } - - // Set element in array. - void set(uint idx, HeapRegion* hr) { - assert(idx < _max_size, "Index %u out of bounds %u", idx, _max_size); - assert(_data[idx] == NULL, "Value must not have been set."); - _data[idx] = hr; - } - - void sort_and_copy_into(HeapRegion** dest, uint num_regions) { - if (_cur_claim_idx == 0) { - return; - } - for (uint i = _cur_claim_idx; i < _max_size; i++) { - assert(_data[i] == NULL, "must be"); - } - QuickSort::sort(_data, _cur_claim_idx, order_regions, true); - for (uint i = num_regions; i < _max_size; i++) { - assert(_data[i] == NULL, "must be"); - } - for (uint i = 0; i < num_regions; i++) { - dest[i] = _data[i]; - } - } - }; - - // Per-region closure. In addition to determining whether a region should be - // added to the candidates, and calculating those regions' gc efficiencies, also - // gather additional statistics. - class G1BuildCandidateRegionsClosure : public HeapRegionClosure { - G1BuildCandidateArray* _array; - - uint _cur_chunk_idx; - uint _cur_chunk_end; - - uint _regions_added; - size_t _reclaimable_bytes_added; - - void add_region(HeapRegion* hr) { - if (_cur_chunk_idx == _cur_chunk_end) { - _array->claim_chunk(_cur_chunk_idx, _cur_chunk_end); - } - assert(_cur_chunk_idx < _cur_chunk_end, "Must be"); - - hr->calc_gc_efficiency(); - _array->set(_cur_chunk_idx, hr); - - _cur_chunk_idx++; - - _regions_added++; - _reclaimable_bytes_added += hr->reclaimable_bytes(); - } - - bool should_add(HeapRegion* hr) { return CollectionSetChooser::should_add(hr); } - - public: - G1BuildCandidateRegionsClosure(G1BuildCandidateArray* array) : - _array(array), - _cur_chunk_idx(0), - _cur_chunk_end(0), - _regions_added(0), - _reclaimable_bytes_added(0) { } - - bool do_heap_region(HeapRegion* r) { - // We will skip any region that's currently used as an old GC - // alloc region (we should not consider those for collection - // before we fill them up). - if (should_add(r) && !G1CollectedHeap::heap()->is_old_gc_alloc_region(r)) { - add_region(r); - } else if (r->is_old()) { - // Keep remembered sets for humongous regions, otherwise clean out remembered - // sets for old regions. - r->rem_set()->clear(true /* only_cardset */); - } else { - assert(r->is_archive() || !r->is_old() || !r->rem_set()->is_tracked(), - "Missed to clear unused remembered set of region %u (%s) that is %s", - r->hrm_index(), r->get_type_str(), r->rem_set()->get_state_str()); - } - return false; - } - - uint regions_added() const { return _regions_added; } - size_t reclaimable_bytes_added() const { return _reclaimable_bytes_added; } - }; - - G1CollectedHeap* _g1h; - HeapRegionClaimer _hrclaimer; - - uint volatile _num_regions_added; - size_t volatile _reclaimable_bytes_added; - - G1BuildCandidateArray _result; - - void update_totals(uint num_regions, size_t reclaimable_bytes) { - if (num_regions > 0) { - assert(reclaimable_bytes > 0, "invariant"); - Atomic::add(num_regions, &_num_regions_added); - Atomic::add(reclaimable_bytes, &_reclaimable_bytes_added); - } else { - assert(reclaimable_bytes == 0, "invariant"); - } - } - -public: - G1BuildCandidateRegionsTask(uint max_num_regions, uint chunk_size, uint num_workers) : - AbstractGangTask("G1 Build Candidate Regions"), - _g1h(G1CollectedHeap::heap()), - _hrclaimer(num_workers), - _num_regions_added(0), - _reclaimable_bytes_added(0), - _result(max_num_regions, chunk_size, num_workers) { } - - void work(uint worker_id) { - G1BuildCandidateRegionsClosure cl(&_result); - _g1h->heap_region_par_iterate_from_worker_offset(&cl, &_hrclaimer, worker_id); - update_totals(cl.regions_added(), cl.reclaimable_bytes_added()); - } - - G1CollectionSetCandidates* get_sorted_candidates() { - HeapRegion** regions = NEW_C_HEAP_ARRAY(HeapRegion*, _num_regions_added, mtGC); - _result.sort_and_copy_into(regions, _num_regions_added); - return new G1CollectionSetCandidates(regions, - _num_regions_added, - _reclaimable_bytes_added); - } -}; - -uint CollectionSetChooser::calculate_work_chunk_size(uint num_workers, uint num_regions) { - assert(num_workers > 0, "Active gc workers should be greater than 0"); - return MAX2(num_regions / num_workers, 1U); -} - -bool CollectionSetChooser::should_add(HeapRegion* hr) { - return !hr->is_young() && - !hr->is_pinned() && - region_occupancy_low_enough_for_evac(hr->live_bytes()) && - hr->rem_set()->is_complete(); -} - -G1CollectionSetCandidates* CollectionSetChooser::build(WorkGang* workers, uint max_num_regions) { - uint num_workers = workers->active_workers(); - uint chunk_size = calculate_work_chunk_size(num_workers, max_num_regions); - - G1BuildCandidateRegionsTask cl(max_num_regions, chunk_size, num_workers); - workers->run_task(&cl, num_workers); - - G1CollectionSetCandidates* result = cl.get_sorted_candidates(); - result->verify(); - return result; -} --- /dev/null 2019-01-25 10:20:53.925519614 +0100 +++ new/src/hotspot/share/gc/g1/g1CollectionSetChooser.cpp 2019-01-25 14:27:02.054301090 +0100 @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1CollectionSetChooser.hpp" +#include "gc/g1/heapRegionRemSet.hpp" +#include "gc/shared/space.inline.hpp" +#include "runtime/atomic.hpp" +#include "utilities/quickSort.hpp" + +// Order regions according to GC efficiency. This will cause regions with a lot +// of live objects and large remembered sets to end up at the end of the array. +// Given that we might skip collecting the last few old regions, if after a few +// mixed GCs the remaining have reclaimable bytes under a certain threshold, the +// hope is that the ones we'll skip are ones with both large remembered sets and +// a lot of live objects, not the ones with just a lot of live objects if we +// ordered according to the amount of reclaimable bytes per region. +static int order_regions(HeapRegion* hr1, HeapRegion* hr2) { + // Make sure that NULL entries are moved to the end. + if (hr1 == NULL) { + if (hr2 == NULL) { + return 0; + } else { + return 1; + } + } else if (hr2 == NULL) { + return -1; + } + + double gc_eff1 = hr1->gc_efficiency(); + double gc_eff2 = hr2->gc_efficiency(); + + if (gc_eff1 > gc_eff2) { + return -1; + } if (gc_eff1 < gc_eff2) { + return 1; + } else { + return 0; + } +} + +// Determine collection set candidates: For all regions determine whether they +// should be a collection set candidates, calculate their efficiency, sort and +// return them as G1CollectionSetCandidates instance. +// Threads calculate the GC efficiency of the regions they get to process, and +// put them into some work area unsorted. At the end the array is sorted and +// copied into the G1CollectionSetCandidates instance; the caller will be the new +// owner of this object. +class G1BuildCandidateRegionsTask : public AbstractGangTask { + + // Work area for building the set of collection set candidates. Contains references + // to heap regions with their GC efficiencies calculated. To reduce contention + // on claiming array elements, worker threads claim parts of this array in chunks; + // Array elements may be NULL as threads might not get enough regions to fill + // up their chunks completely. + // Final sorting will remove them. + class G1BuildCandidateArray : public StackObj { + + uint const _max_size; + uint const _chunk_size; + + HeapRegion** _data; + + uint volatile _cur_claim_idx; + + // Calculates the maximum array size that will be used. + static uint required_array_size(uint num_regions, uint num_workers, uint chunk_size) { + uint const max_waste = num_workers * chunk_size; + // The array should be aligned with respect to chunk_size. + uint const aligned_num_regions = ((num_regions + chunk_size - 1) / chunk_size) * chunk_size; + + return aligned_num_regions + max_waste; + } + + public: + G1BuildCandidateArray(uint max_num_regions, uint num_workers, uint chunk_size) : + _max_size(required_array_size(max_num_regions, num_workers, chunk_size)), + _chunk_size(chunk_size), + _data(NEW_C_HEAP_ARRAY(HeapRegion*, _max_size, mtGC)), + _cur_claim_idx(0) { + for (uint i = 0; i < _max_size; i++) { + _data[i] = NULL; + } + } + + ~G1BuildCandidateArray() { + FREE_C_HEAP_ARRAY(HeapRegion*, _data); + } + + // Claim a new chunk, returning its bounds [from, to[. + void claim_chunk(uint& from, uint& to) { + uint result = Atomic::add(_chunk_size, &_cur_claim_idx); + assert(_max_size > result - 1, + "Array too small, is %u should be %u with chunk size %u.", + _max_size, result, _chunk_size); + from = result - _chunk_size; + to = result; + } + + // Set element in array. + void set(uint idx, HeapRegion* hr) { + assert(idx < _max_size, "Index %u out of bounds %u", idx, _max_size); + assert(_data[idx] == NULL, "Value must not have been set."); + _data[idx] = hr; + } + + void sort_and_copy_into(HeapRegion** dest, uint num_regions) { + if (_cur_claim_idx == 0) { + return; + } + for (uint i = _cur_claim_idx; i < _max_size; i++) { + assert(_data[i] == NULL, "must be"); + } + QuickSort::sort(_data, _cur_claim_idx, order_regions, true); + for (uint i = num_regions; i < _max_size; i++) { + assert(_data[i] == NULL, "must be"); + } + for (uint i = 0; i < num_regions; i++) { + dest[i] = _data[i]; + } + } + }; + + // Per-region closure. In addition to determining whether a region should be + // added to the candidates, and calculating those regions' gc efficiencies, also + // gather additional statistics. + class G1BuildCandidateRegionsClosure : public HeapRegionClosure { + G1BuildCandidateArray* _array; + + uint _cur_chunk_idx; + uint _cur_chunk_end; + + uint _regions_added; + size_t _reclaimable_bytes_added; + + void add_region(HeapRegion* hr) { + if (_cur_chunk_idx == _cur_chunk_end) { + _array->claim_chunk(_cur_chunk_idx, _cur_chunk_end); + } + assert(_cur_chunk_idx < _cur_chunk_end, "Must be"); + + hr->calc_gc_efficiency(); + _array->set(_cur_chunk_idx, hr); + + _cur_chunk_idx++; + + _regions_added++; + _reclaimable_bytes_added += hr->reclaimable_bytes(); + } + + bool should_add(HeapRegion* hr) { return G1CollectionSetChooser::should_add(hr); } + + public: + G1BuildCandidateRegionsClosure(G1BuildCandidateArray* array) : + _array(array), + _cur_chunk_idx(0), + _cur_chunk_end(0), + _regions_added(0), + _reclaimable_bytes_added(0) { } + + bool do_heap_region(HeapRegion* r) { + // We will skip any region that's currently used as an old GC + // alloc region (we should not consider those for collection + // before we fill them up). + if (should_add(r) && !G1CollectedHeap::heap()->is_old_gc_alloc_region(r)) { + add_region(r); + } else if (r->is_old()) { + // Keep remembered sets for humongous regions, otherwise clean out remembered + // sets for old regions. + r->rem_set()->clear(true /* only_cardset */); + } else { + assert(r->is_archive() || !r->is_old() || !r->rem_set()->is_tracked(), + "Missed to clear unused remembered set of region %u (%s) that is %s", + r->hrm_index(), r->get_type_str(), r->rem_set()->get_state_str()); + } + return false; + } + + uint regions_added() const { return _regions_added; } + size_t reclaimable_bytes_added() const { return _reclaimable_bytes_added; } + }; + + G1CollectedHeap* _g1h; + HeapRegionClaimer _hrclaimer; + + uint volatile _num_regions_added; + size_t volatile _reclaimable_bytes_added; + + G1BuildCandidateArray _result; + + void update_totals(uint num_regions, size_t reclaimable_bytes) { + if (num_regions > 0) { + assert(reclaimable_bytes > 0, "invariant"); + Atomic::add(num_regions, &_num_regions_added); + Atomic::add(reclaimable_bytes, &_reclaimable_bytes_added); + } else { + assert(reclaimable_bytes == 0, "invariant"); + } + } + +public: + G1BuildCandidateRegionsTask(uint max_num_regions, uint chunk_size, uint num_workers) : + AbstractGangTask("G1 Build Candidate Regions"), + _g1h(G1CollectedHeap::heap()), + _hrclaimer(num_workers), + _num_regions_added(0), + _reclaimable_bytes_added(0), + _result(max_num_regions, chunk_size, num_workers) { } + + void work(uint worker_id) { + G1BuildCandidateRegionsClosure cl(&_result); + _g1h->heap_region_par_iterate_from_worker_offset(&cl, &_hrclaimer, worker_id); + update_totals(cl.regions_added(), cl.reclaimable_bytes_added()); + } + + G1CollectionSetCandidates* get_sorted_candidates() { + HeapRegion** regions = NEW_C_HEAP_ARRAY(HeapRegion*, _num_regions_added, mtGC); + _result.sort_and_copy_into(regions, _num_regions_added); + return new G1CollectionSetCandidates(regions, + _num_regions_added, + _reclaimable_bytes_added); + } +}; + +uint G1CollectionSetChooser::calculate_work_chunk_size(uint num_workers, uint num_regions) { + assert(num_workers > 0, "Active gc workers should be greater than 0"); + return MAX2(num_regions / num_workers, 1U); +} + +bool G1CollectionSetChooser::should_add(HeapRegion* hr) { + return !hr->is_young() && + !hr->is_pinned() && + region_occupancy_low_enough_for_evac(hr->live_bytes()) && + hr->rem_set()->is_complete(); +} + +G1CollectionSetCandidates* G1CollectionSetChooser::build(WorkGang* workers, uint max_num_regions) { + uint num_workers = workers->active_workers(); + uint chunk_size = calculate_work_chunk_size(num_workers, max_num_regions); + + G1BuildCandidateRegionsTask cl(max_num_regions, chunk_size, num_workers); + workers->run_task(&cl, num_workers); + + G1CollectionSetCandidates* result = cl.get_sorted_candidates(); + result->verify(); + return result; +} --- old/src/hotspot/share/gc/g1/collectionSetChooser.hpp 2019-01-25 14:27:04.486376087 +0100 +++ /dev/null 2019-01-25 10:20:53.925519614 +0100 @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHARE_GC_G1_COLLECTIONSETCHOOSER_HPP -#define SHARE_GC_G1_COLLECTIONSETCHOOSER_HPP - -#include "gc/g1/heapRegion.hpp" -#include "memory/allocation.hpp" -#include "runtime/globals.hpp" - -class G1CollectionSetCandidates; -class WorkGang; - -// Helper class to calculate collection set candidates, and containing some related -// methods. -class CollectionSetChooser : public AllStatic { - static uint calculate_work_chunk_size(uint num_workers, uint num_regions); -public: - CollectionSetChooser(); - - static size_t mixed_gc_live_threshold_bytes() { - return HeapRegion::GrainBytes * (size_t) G1MixedGCLiveThresholdPercent / 100; - } - - static bool region_occupancy_low_enough_for_evac(size_t live_bytes) { - return live_bytes < mixed_gc_live_threshold_bytes(); - } - - // Determine whether to add the given region to the collection set candidates or - // not. Currently, we skip pinned regions and regions whose live - // bytes are over the threshold. Humongous regions may be reclaimed during cleanup. - // Regions also need a complete remembered set to be a candidate. - static bool should_add(HeapRegion* hr); - - // Build and return set of collection set candidates sorted by decreasing gc - // efficiency. - static G1CollectionSetCandidates* build(WorkGang* workers, uint max_num_regions); -}; - -#endif // SHARE_GC_G1_COLLECTIONSETCHOOSER_HPP --- /dev/null 2019-01-25 10:20:53.925519614 +0100 +++ new/src/hotspot/share/gc/g1/g1CollectionSetChooser.hpp 2019-01-25 14:27:03.928358880 +0100 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_GC_G1_G1COLLECTIONSETCHOOSER_HPP +#define SHARE_GC_G1_G1COLLECTIONSETCHOOSER_HPP + +#include "gc/g1/heapRegion.hpp" +#include "memory/allocation.hpp" +#include "runtime/globals.hpp" + +class G1CollectionSetCandidates; +class WorkGang; + +// Helper class to calculate collection set candidates, and containing some related +// methods. +class G1CollectionSetChooser : public AllStatic { + static uint calculate_work_chunk_size(uint num_workers, uint num_regions); +public: + G1CollectionSetChooser(); + + static size_t mixed_gc_live_threshold_bytes() { + return HeapRegion::GrainBytes * (size_t) G1MixedGCLiveThresholdPercent / 100; + } + + static bool region_occupancy_low_enough_for_evac(size_t live_bytes) { + return live_bytes < mixed_gc_live_threshold_bytes(); + } + + // Determine whether to add the given region to the collection set candidates or + // not. Currently, we skip pinned regions and regions whose live + // bytes are over the threshold. Humongous regions may be reclaimed during cleanup. + // Regions also need a complete remembered set to be a candidate. + static bool should_add(HeapRegion* hr); + + // Build and return set of collection set candidates sorted by decreasing gc + // efficiency. + static G1CollectionSetCandidates* build(WorkGang* workers, uint max_num_regions); +}; + +#endif // SHARE_GC_G1_G1COLLECTIONSETCHOOSER_HPP