8336086: G1: Use one G1CardSet instance for all young regions
Reviewed-by: tschatzl, ayang
This commit is contained in:
parent
4c344335fe
commit
f536f5ab68
@ -244,6 +244,10 @@ class G1CardSetHashTable : public CHeapObj<mtGCCardSet> {
|
|||||||
using CHTScanTask = CardSetHash::ScanTask;
|
using CHTScanTask = CardSetHash::ScanTask;
|
||||||
|
|
||||||
const static uint BucketClaimSize = 16;
|
const static uint BucketClaimSize = 16;
|
||||||
|
// The claim size for group cardsets should be smaller to facilitate
|
||||||
|
// better work distribution. The group cardsets should be larger than
|
||||||
|
// the per region cardsets.
|
||||||
|
const static uint GroupBucketClaimSize = 4;
|
||||||
// Did we insert at least one card in the table?
|
// Did we insert at least one card in the table?
|
||||||
bool volatile _inserted_card;
|
bool volatile _inserted_card;
|
||||||
|
|
||||||
@ -347,7 +351,15 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void reset_table_scanner() {
|
void reset_table_scanner() {
|
||||||
_table_scanner.set(&_table, BucketClaimSize);
|
reset_table_scanner(BucketClaimSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_table_scanner_for_groups() {
|
||||||
|
reset_table_scanner(GroupBucketClaimSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset_table_scanner(uint claim_size) {
|
||||||
|
_table_scanner.set(&_table, claim_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void grow() {
|
void grow() {
|
||||||
@ -1042,3 +1054,7 @@ void G1CardSet::clear() {
|
|||||||
void G1CardSet::reset_table_scanner() {
|
void G1CardSet::reset_table_scanner() {
|
||||||
_table->reset_table_scanner();
|
_table->reset_table_scanner();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void G1CardSet::reset_table_scanner_for_groups() {
|
||||||
|
_table->reset_table_scanner_for_groups();
|
||||||
|
}
|
||||||
|
@ -380,6 +380,8 @@ public:
|
|||||||
|
|
||||||
void reset_table_scanner();
|
void reset_table_scanner();
|
||||||
|
|
||||||
|
void reset_table_scanner_for_groups();
|
||||||
|
|
||||||
// Iterate over the container, calling a method on every card or card range contained
|
// Iterate over the container, calling a method on every card or card range contained
|
||||||
// in the card container.
|
// in the card container.
|
||||||
// For every container, first calls
|
// For every container, first calls
|
||||||
|
@ -1159,6 +1159,8 @@ G1CollectedHeap::G1CollectedHeap() :
|
|||||||
_rem_set(nullptr),
|
_rem_set(nullptr),
|
||||||
_card_set_config(),
|
_card_set_config(),
|
||||||
_card_set_freelist_pool(G1CardSetConfiguration::num_mem_object_types()),
|
_card_set_freelist_pool(G1CardSetConfiguration::num_mem_object_types()),
|
||||||
|
_young_regions_cardset_mm(card_set_config(), card_set_freelist_pool()),
|
||||||
|
_young_regions_cardset(card_set_config(), &_young_regions_cardset_mm),
|
||||||
_cm(nullptr),
|
_cm(nullptr),
|
||||||
_cm_thread(nullptr),
|
_cm_thread(nullptr),
|
||||||
_cr(nullptr),
|
_cr(nullptr),
|
||||||
@ -2693,6 +2695,7 @@ bool G1CollectedHeap::is_old_gc_alloc_region(G1HeapRegion* hr) {
|
|||||||
void G1CollectedHeap::set_region_short_lived_locked(G1HeapRegion* hr) {
|
void G1CollectedHeap::set_region_short_lived_locked(G1HeapRegion* hr) {
|
||||||
_eden.add(hr);
|
_eden.add(hr);
|
||||||
_policy->set_region_eden(hr);
|
_policy->set_region_eden(hr);
|
||||||
|
hr->install_group_cardset(young_regions_cardset());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
@ -2902,6 +2905,8 @@ G1HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size, G1HeapRegio
|
|||||||
new_alloc_region->set_survivor();
|
new_alloc_region->set_survivor();
|
||||||
_survivor.add(new_alloc_region);
|
_survivor.add(new_alloc_region);
|
||||||
register_new_survivor_region_with_region_attr(new_alloc_region);
|
register_new_survivor_region_with_region_attr(new_alloc_region);
|
||||||
|
// Install the group cardset.
|
||||||
|
new_alloc_region->install_group_cardset(young_regions_cardset());
|
||||||
} else {
|
} else {
|
||||||
new_alloc_region->set_old();
|
new_alloc_region->set_old();
|
||||||
}
|
}
|
||||||
@ -3043,3 +3048,7 @@ void G1CollectedHeap::finish_codecache_marking_cycle() {
|
|||||||
CodeCache::on_gc_marking_cycle_finish();
|
CodeCache::on_gc_marking_cycle_finish();
|
||||||
CodeCache::arm_all_nmethods();
|
CodeCache::arm_all_nmethods();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void G1CollectedHeap::prepare_group_cardsets_for_scan () {
|
||||||
|
_young_regions_cardset.reset_table_scanner_for_groups();
|
||||||
|
}
|
||||||
|
@ -779,7 +779,19 @@ private:
|
|||||||
|
|
||||||
G1MonotonicArenaFreePool _card_set_freelist_pool;
|
G1MonotonicArenaFreePool _card_set_freelist_pool;
|
||||||
|
|
||||||
|
// Group cardsets
|
||||||
|
G1CardSetMemoryManager _young_regions_cardset_mm;
|
||||||
|
G1CardSet _young_regions_cardset;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
G1CardSetConfiguration* card_set_config() { return &_card_set_config; }
|
||||||
|
|
||||||
|
G1CardSet* young_regions_cardset() { return &_young_regions_cardset; };
|
||||||
|
|
||||||
|
G1CardSetMemoryManager* young_regions_card_set_mm() { return &_young_regions_cardset_mm; }
|
||||||
|
|
||||||
|
void prepare_group_cardsets_for_scan();
|
||||||
|
|
||||||
// After a collection pause, reset eden and the collection set.
|
// After a collection pause, reset eden and the collection set.
|
||||||
void clear_eden();
|
void clear_eden();
|
||||||
void clear_collection_set();
|
void clear_collection_set();
|
||||||
|
@ -297,7 +297,7 @@ double G1CollectionSet::finalize_young_part(double target_pause_time_ms, G1Survi
|
|||||||
|
|
||||||
verify_young_cset_indices();
|
verify_young_cset_indices();
|
||||||
|
|
||||||
double predicted_base_time_ms = _policy->predict_base_time_ms(pending_cards);
|
double predicted_base_time_ms = _policy->predict_base_time_ms(pending_cards, _g1h->young_regions_cardset()->occupied());
|
||||||
// Base time already includes the whole remembered set related time, so do not add that here
|
// Base time already includes the whole remembered set related time, so do not add that here
|
||||||
// again.
|
// again.
|
||||||
double predicted_eden_time = _policy->predict_young_region_other_time_ms(eden_region_length) +
|
double predicted_eden_time = _policy->predict_young_region_other_time_ms(eden_region_length) +
|
||||||
|
@ -2980,6 +2980,7 @@ G1PrintRegionLivenessInfoClosure::G1PrintRegionLivenessInfoClosure(const char* p
|
|||||||
_total_capacity_bytes(0),
|
_total_capacity_bytes(0),
|
||||||
_total_live_bytes(0),
|
_total_live_bytes(0),
|
||||||
_total_remset_bytes(0),
|
_total_remset_bytes(0),
|
||||||
|
_young_cardset_bytes_per_region(0),
|
||||||
_total_code_roots_bytes(0)
|
_total_code_roots_bytes(0)
|
||||||
{
|
{
|
||||||
if (!log_is_enabled(Trace, gc, liveness)) {
|
if (!log_is_enabled(Trace, gc, liveness)) {
|
||||||
@ -2990,6 +2991,13 @@ G1PrintRegionLivenessInfoClosure::G1PrintRegionLivenessInfoClosure(const char* p
|
|||||||
MemRegion reserved = g1h->reserved();
|
MemRegion reserved = g1h->reserved();
|
||||||
double now = os::elapsedTime();
|
double now = os::elapsedTime();
|
||||||
|
|
||||||
|
uint num_young_regions = g1h->young_regions_count();
|
||||||
|
size_t young_cardset_bytes = g1h->young_regions_cardset()->mem_size();
|
||||||
|
|
||||||
|
if (num_young_regions > 0) {
|
||||||
|
_young_cardset_bytes_per_region = young_cardset_bytes / num_young_regions;
|
||||||
|
}
|
||||||
|
|
||||||
// Print the header of the output.
|
// Print the header of the output.
|
||||||
log_trace(gc, liveness)(G1PPRL_LINE_PREFIX" PHASE %s @ %1.3f", phase_name, now);
|
log_trace(gc, liveness)(G1PPRL_LINE_PREFIX" PHASE %s @ %1.3f", phase_name, now);
|
||||||
log_trace(gc, liveness)(G1PPRL_LINE_PREFIX" HEAP"
|
log_trace(gc, liveness)(G1PPRL_LINE_PREFIX" HEAP"
|
||||||
@ -3041,6 +3049,10 @@ bool G1PrintRegionLivenessInfoClosure::do_heap_region(G1HeapRegion* r) {
|
|||||||
const char* remset_type = r->rem_set()->get_short_state_str();
|
const char* remset_type = r->rem_set()->get_short_state_str();
|
||||||
FormatBuffer<16> gc_efficiency("");
|
FormatBuffer<16> gc_efficiency("");
|
||||||
|
|
||||||
|
if (r->is_young()) {
|
||||||
|
remset_bytes = _young_cardset_bytes_per_region;
|
||||||
|
}
|
||||||
|
|
||||||
_total_used_bytes += used_bytes;
|
_total_used_bytes += used_bytes;
|
||||||
_total_capacity_bytes += capacity_bytes;
|
_total_capacity_bytes += capacity_bytes;
|
||||||
_total_live_bytes += live_bytes;
|
_total_live_bytes += live_bytes;
|
||||||
|
@ -958,6 +958,8 @@ class G1PrintRegionLivenessInfoClosure : public G1HeapRegionClosure {
|
|||||||
// Accumulator for the remembered set size
|
// Accumulator for the remembered set size
|
||||||
size_t _total_remset_bytes;
|
size_t _total_remset_bytes;
|
||||||
|
|
||||||
|
size_t _young_cardset_bytes_per_region;
|
||||||
|
|
||||||
// Accumulator for code roots memory size
|
// Accumulator for code roots memory size
|
||||||
size_t _total_code_roots_bytes;
|
size_t _total_code_roots_bytes;
|
||||||
|
|
||||||
|
@ -254,21 +254,18 @@ uint64_t G1ConcurrentRefine::adjust_threads_wait_ms() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class G1ConcurrentRefine::RemSetSamplingClosure : public G1HeapRegionClosure {
|
class G1ConcurrentRefine::RemSetSamplingClosure : public G1HeapRegionClosure {
|
||||||
size_t _sampled_card_rs_length;
|
|
||||||
size_t _sampled_code_root_rs_length;
|
size_t _sampled_code_root_rs_length;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RemSetSamplingClosure() :
|
RemSetSamplingClosure() :
|
||||||
_sampled_card_rs_length(0), _sampled_code_root_rs_length(0) {}
|
_sampled_code_root_rs_length(0) {}
|
||||||
|
|
||||||
bool do_heap_region(G1HeapRegion* r) override {
|
bool do_heap_region(G1HeapRegion* r) override {
|
||||||
G1HeapRegionRemSet* rem_set = r->rem_set();
|
G1HeapRegionRemSet* rem_set = r->rem_set();
|
||||||
_sampled_card_rs_length += rem_set->occupied();
|
|
||||||
_sampled_code_root_rs_length += rem_set->code_roots_list_length();
|
_sampled_code_root_rs_length += rem_set->code_roots_list_length();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sampled_card_rs_length() const { return _sampled_card_rs_length; }
|
|
||||||
size_t sampled_code_root_rs_length() const { return _sampled_code_root_rs_length; }
|
size_t sampled_code_root_rs_length() const { return _sampled_code_root_rs_length; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -286,10 +283,15 @@ public:
|
|||||||
// gen size to keep pause time length goal.
|
// gen size to keep pause time length goal.
|
||||||
void G1ConcurrentRefine::adjust_young_list_target_length() {
|
void G1ConcurrentRefine::adjust_young_list_target_length() {
|
||||||
if (_policy->use_adaptive_young_list_length()) {
|
if (_policy->use_adaptive_young_list_length()) {
|
||||||
|
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||||
|
G1CollectionSet* cset = g1h->collection_set();
|
||||||
RemSetSamplingClosure cl;
|
RemSetSamplingClosure cl;
|
||||||
G1CollectionSet* cset = G1CollectedHeap::heap()->collection_set();
|
|
||||||
cset->iterate(&cl);
|
cset->iterate(&cl);
|
||||||
_policy->revise_young_list_target_length(cl.sampled_card_rs_length(), cl.sampled_code_root_rs_length());
|
|
||||||
|
size_t card_rs_length = g1h->young_regions_cardset()->occupied();
|
||||||
|
|
||||||
|
size_t sampled_code_root_rs_length = cl.sampled_code_root_rs_length();
|
||||||
|
_policy->revise_young_list_target_length(card_rs_length, sampled_code_root_rs_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +172,7 @@ public:
|
|||||||
|
|
||||||
bool do_heap_region(G1HeapRegion* hr) {
|
bool do_heap_region(G1HeapRegion* hr) {
|
||||||
hr->prepare_for_full_gc();
|
hr->prepare_for_full_gc();
|
||||||
|
hr->uninstall_group_cardset();
|
||||||
G1CollectedHeap::heap()->prepare_region_for_full_compaction(hr);
|
G1CollectedHeap::heap()->prepare_region_for_full_compaction(hr);
|
||||||
_collector->before_marking_update_attribute_table(hr);
|
_collector->before_marking_update_attribute_table(hr);
|
||||||
return false;
|
return false;
|
||||||
@ -247,6 +248,8 @@ void G1FullCollector::complete_collection() {
|
|||||||
|
|
||||||
_heap->resize_all_tlabs();
|
_heap->resize_all_tlabs();
|
||||||
|
|
||||||
|
_heap->young_regions_cardset()->clear();
|
||||||
|
|
||||||
_heap->policy()->record_full_collection_end();
|
_heap->policy()->record_full_collection_end();
|
||||||
_heap->gc_epilogue(true);
|
_heap->gc_epilogue(true);
|
||||||
|
|
||||||
|
@ -119,6 +119,7 @@ void G1HeapRegion::hr_clear(bool clear_space) {
|
|||||||
clear_young_index_in_cset();
|
clear_young_index_in_cset();
|
||||||
clear_index_in_opt_cset();
|
clear_index_in_opt_cset();
|
||||||
uninstall_surv_rate_group();
|
uninstall_surv_rate_group();
|
||||||
|
uninstall_group_cardset();
|
||||||
set_free();
|
set_free();
|
||||||
reset_pre_dummy_top();
|
reset_pre_dummy_top();
|
||||||
|
|
||||||
@ -215,6 +216,9 @@ void G1HeapRegion::clear_humongous() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void G1HeapRegion::prepare_remset_for_scan() {
|
void G1HeapRegion::prepare_remset_for_scan() {
|
||||||
|
if (is_young()) {
|
||||||
|
uninstall_group_cardset();
|
||||||
|
}
|
||||||
_rem_set->reset_table_scanner();
|
_rem_set->reset_table_scanner();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "runtime/mutex.hpp"
|
#include "runtime/mutex.hpp"
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
|
|
||||||
|
class G1CardSet;
|
||||||
class G1CardSetConfiguration;
|
class G1CardSetConfiguration;
|
||||||
class G1CollectedHeap;
|
class G1CollectedHeap;
|
||||||
class G1CMBitMap;
|
class G1CMBitMap;
|
||||||
@ -508,6 +509,9 @@ public:
|
|||||||
void install_surv_rate_group(G1SurvRateGroup* surv_rate_group);
|
void install_surv_rate_group(G1SurvRateGroup* surv_rate_group);
|
||||||
void uninstall_surv_rate_group();
|
void uninstall_surv_rate_group();
|
||||||
|
|
||||||
|
void install_group_cardset(G1CardSet* group_cardset);
|
||||||
|
void uninstall_group_cardset();
|
||||||
|
|
||||||
void record_surv_words_in_group(size_t words_survived);
|
void record_surv_words_in_group(size_t words_survived);
|
||||||
|
|
||||||
// Determine if an address is in the parsable or the to-be-scrubbed area.
|
// Determine if an address is in the parsable or the to-be-scrubbed area.
|
||||||
|
@ -511,4 +511,12 @@ inline void G1HeapRegion::add_pinned_object_count(size_t value) {
|
|||||||
Atomic::add(&_pinned_object_count, value, memory_order_relaxed);
|
Atomic::add(&_pinned_object_count, value, memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void G1HeapRegion::install_group_cardset(G1CardSet* group_cardset) {
|
||||||
|
_rem_set->install_group_cardset(group_cardset);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void G1HeapRegion::uninstall_group_cardset() {
|
||||||
|
_rem_set->uninstall_group_cardset();
|
||||||
|
}
|
||||||
|
|
||||||
#endif // SHARE_GC_G1_G1HEAPREGION_INLINE_HPP
|
#endif // SHARE_GC_G1_G1HEAPREGION_INLINE_HPP
|
||||||
|
@ -55,11 +55,19 @@ void G1HeapRegionRemSet::initialize(MemRegion reserved) {
|
|||||||
_heap_base_address = reserved.start();
|
_heap_base_address = reserved.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void G1HeapRegionRemSet::uninstall_group_cardset() {
|
||||||
|
if (_saved_card_set != nullptr) {
|
||||||
|
_card_set = _saved_card_set;
|
||||||
|
_saved_card_set = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
G1HeapRegionRemSet::G1HeapRegionRemSet(G1HeapRegion* hr,
|
G1HeapRegionRemSet::G1HeapRegionRemSet(G1HeapRegion* hr,
|
||||||
G1CardSetConfiguration* config) :
|
G1CardSetConfiguration* config) :
|
||||||
_code_roots(),
|
_code_roots(),
|
||||||
_card_set_mm(config, G1CollectedHeap::heap()->card_set_freelist_pool()),
|
_card_set_mm(config, G1CollectedHeap::heap()->card_set_freelist_pool()),
|
||||||
_card_set(config, &_card_set_mm),
|
_card_set(new G1CardSet(config, &_card_set_mm)),
|
||||||
|
_saved_card_set(nullptr),
|
||||||
_hr(hr),
|
_hr(hr),
|
||||||
_state(Untracked) { }
|
_state(Untracked) { }
|
||||||
|
|
||||||
@ -68,11 +76,12 @@ void G1HeapRegionRemSet::clear_fcc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void G1HeapRegionRemSet::clear(bool only_cardset, bool keep_tracked) {
|
void G1HeapRegionRemSet::clear(bool only_cardset, bool keep_tracked) {
|
||||||
|
assert(_saved_card_set == nullptr, "pre-condition");
|
||||||
if (!only_cardset) {
|
if (!only_cardset) {
|
||||||
_code_roots.clear();
|
_code_roots.clear();
|
||||||
}
|
}
|
||||||
clear_fcc();
|
clear_fcc();
|
||||||
_card_set.clear();
|
_card_set->clear();
|
||||||
if (!keep_tracked) {
|
if (!keep_tracked) {
|
||||||
set_state_untracked();
|
set_state_untracked();
|
||||||
} else {
|
} else {
|
||||||
@ -83,7 +92,7 @@ void G1HeapRegionRemSet::clear(bool only_cardset, bool keep_tracked) {
|
|||||||
|
|
||||||
void G1HeapRegionRemSet::reset_table_scanner() {
|
void G1HeapRegionRemSet::reset_table_scanner() {
|
||||||
_code_roots.reset_table_scanner();
|
_code_roots.reset_table_scanner();
|
||||||
_card_set.reset_table_scanner();
|
_card_set->reset_table_scanner();
|
||||||
}
|
}
|
||||||
|
|
||||||
G1MonotonicArenaMemoryStats G1HeapRegionRemSet::card_set_memory_stats() const {
|
G1MonotonicArenaMemoryStats G1HeapRegionRemSet::card_set_memory_stats() const {
|
||||||
|
@ -47,7 +47,8 @@ class G1HeapRegionRemSet : public CHeapObj<mtGC> {
|
|||||||
G1CardSetMemoryManager _card_set_mm;
|
G1CardSetMemoryManager _card_set_mm;
|
||||||
|
|
||||||
// The set of cards in the Java heap
|
// The set of cards in the Java heap
|
||||||
G1CardSet _card_set;
|
G1CardSet* _card_set;
|
||||||
|
G1CardSet* _saved_card_set;
|
||||||
|
|
||||||
G1HeapRegion* _hr;
|
G1HeapRegion* _hr;
|
||||||
|
|
||||||
@ -58,9 +59,24 @@ class G1HeapRegionRemSet : public CHeapObj<mtGC> {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
G1HeapRegionRemSet(G1HeapRegion* hr, G1CardSetConfiguration* config);
|
G1HeapRegionRemSet(G1HeapRegion* hr, G1CardSetConfiguration* config);
|
||||||
|
~G1HeapRegionRemSet() { delete _card_set; }
|
||||||
|
|
||||||
bool cardset_is_empty() const {
|
bool cardset_is_empty() const {
|
||||||
return _card_set.is_empty();
|
return _card_set->is_empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void install_group_cardset(G1CardSet* group_cardset) {
|
||||||
|
assert(group_cardset != nullptr, "pre-condition");
|
||||||
|
assert(_saved_card_set == nullptr, "pre-condition");
|
||||||
|
|
||||||
|
_saved_card_set = _card_set;
|
||||||
|
_card_set = group_cardset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninstall_group_cardset();
|
||||||
|
|
||||||
|
bool has_group_cardset() {
|
||||||
|
return _saved_card_set != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_empty() const {
|
bool is_empty() const {
|
||||||
@ -68,7 +84,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool occupancy_less_or_equal_than(size_t occ) const {
|
bool occupancy_less_or_equal_than(size_t occ) const {
|
||||||
return (code_roots_list_length() == 0) && _card_set.occupancy_less_or_equal_to(occ);
|
return (code_roots_list_length() == 0) && _card_set->occupancy_less_or_equal_to(occ);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate the card based remembered set for merging them into the card table.
|
// Iterate the card based remembered set for merging them into the card table.
|
||||||
@ -77,10 +93,15 @@ public:
|
|||||||
template <class CardOrRangeVisitor>
|
template <class CardOrRangeVisitor>
|
||||||
inline void iterate_for_merge(CardOrRangeVisitor& cl);
|
inline void iterate_for_merge(CardOrRangeVisitor& cl);
|
||||||
|
|
||||||
|
template <class CardOrRangeVisitor>
|
||||||
|
inline static void iterate_for_merge(G1CardSet* card_set, CardOrRangeVisitor& cl);
|
||||||
|
|
||||||
size_t occupied() {
|
size_t occupied() {
|
||||||
return _card_set.occupied();
|
return _card_set->occupied();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
G1CardSet* card_set() { return _card_set; }
|
||||||
|
|
||||||
static void initialize(MemRegion reserved);
|
static void initialize(MemRegion reserved);
|
||||||
|
|
||||||
// Coarsening statistics since VM start.
|
// Coarsening statistics since VM start.
|
||||||
@ -125,13 +146,13 @@ public:
|
|||||||
// The actual # of bytes this hr_remset takes up. Also includes the code
|
// The actual # of bytes this hr_remset takes up. Also includes the code
|
||||||
// root set.
|
// root set.
|
||||||
size_t mem_size() {
|
size_t mem_size() {
|
||||||
return _card_set.mem_size()
|
return _card_set->mem_size()
|
||||||
+ (sizeof(G1HeapRegionRemSet) - sizeof(G1CardSet)) // Avoid double-counting G1CardSet.
|
+ (sizeof(G1HeapRegionRemSet) - sizeof(G1CardSet)) // Avoid double-counting G1CardSet.
|
||||||
+ code_roots_mem_size();
|
+ code_roots_mem_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t unused_mem_size() {
|
size_t unused_mem_size() {
|
||||||
return _card_set.unused_mem_size();
|
return _card_set->unused_mem_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the memory occupancy of all static data structures associated
|
// Returns the memory occupancy of all static data structures associated
|
||||||
|
@ -108,13 +108,17 @@ public:
|
|||||||
|
|
||||||
template <class CardOrRangeVisitor>
|
template <class CardOrRangeVisitor>
|
||||||
inline void G1HeapRegionRemSet::iterate_for_merge(CardOrRangeVisitor& cl) {
|
inline void G1HeapRegionRemSet::iterate_for_merge(CardOrRangeVisitor& cl) {
|
||||||
G1HeapRegionRemSetMergeCardClosure<CardOrRangeVisitor, G1ContainerCardsOrRanges> cl2(&_card_set,
|
iterate_for_merge(_card_set, cl);
|
||||||
cl,
|
|
||||||
_card_set.config()->log2_card_regions_per_heap_region(),
|
|
||||||
_card_set.config()->log2_cards_per_card_region());
|
|
||||||
_card_set.iterate_containers(&cl2, true /* at_safepoint */);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class CardOrRangeVisitor>
|
||||||
|
void G1HeapRegionRemSet::iterate_for_merge(G1CardSet* card_set, CardOrRangeVisitor& cl) {
|
||||||
|
G1HeapRegionRemSetMergeCardClosure<CardOrRangeVisitor, G1ContainerCardsOrRanges> cl2(card_set,
|
||||||
|
cl,
|
||||||
|
card_set->config()->log2_card_regions_per_heap_region(),
|
||||||
|
card_set->config()->log2_cards_per_card_region());
|
||||||
|
card_set->iterate_containers(&cl2, true /* at_safepoint */);
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t G1HeapRegionRemSet::to_card(OopOrNarrowOopStar from) const {
|
uintptr_t G1HeapRegionRemSet::to_card(OopOrNarrowOopStar from) const {
|
||||||
return pointer_delta(from, _heap_base_address, 1) >> CardTable::card_shift();
|
return pointer_delta(from, _heap_base_address, 1) >> CardTable::card_shift();
|
||||||
@ -130,18 +134,18 @@ void G1HeapRegionRemSet::add_reference(OopOrNarrowOopStar from, uint tid) {
|
|||||||
// We can't check whether the card is in the remembered set - the card container
|
// We can't check whether the card is in the remembered set - the card container
|
||||||
// may be coarsened just now.
|
// may be coarsened just now.
|
||||||
//assert(contains_reference(from), "We just found " PTR_FORMAT " in the FromCardCache", p2i(from));
|
//assert(contains_reference(from), "We just found " PTR_FORMAT " in the FromCardCache", p2i(from));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_card_set.add_card(to_card(from));
|
_card_set->add_card(to_card(from));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool G1HeapRegionRemSet::contains_reference(OopOrNarrowOopStar from) {
|
bool G1HeapRegionRemSet::contains_reference(OopOrNarrowOopStar from) {
|
||||||
return _card_set.contains_card(to_card(from));
|
return _card_set->contains_card(to_card(from));
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1HeapRegionRemSet::print_info(outputStream* st, OopOrNarrowOopStar from) {
|
void G1HeapRegionRemSet::print_info(outputStream* st, OopOrNarrowOopStar from) {
|
||||||
_card_set.print_info(st, to_card(from));
|
_card_set->print_info(st, to_card(from));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SHARE_VM_GC_G1_G1HEAPREGIONREMSET_INLINE_HPP
|
#endif // SHARE_VM_GC_G1_G1HEAPREGIONREMSET_INLINE_HPP
|
||||||
|
@ -1089,6 +1089,11 @@ double G1Policy::predict_base_time_ms(size_t pending_cards,
|
|||||||
double G1Policy::predict_base_time_ms(size_t pending_cards) const {
|
double G1Policy::predict_base_time_ms(size_t pending_cards) const {
|
||||||
bool for_young_only_phase = collector_state()->in_young_only_phase();
|
bool for_young_only_phase = collector_state()->in_young_only_phase();
|
||||||
size_t card_rs_length = _analytics->predict_card_rs_length(for_young_only_phase);
|
size_t card_rs_length = _analytics->predict_card_rs_length(for_young_only_phase);
|
||||||
|
return predict_base_time_ms(pending_cards, card_rs_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
double G1Policy::predict_base_time_ms(size_t pending_cards, size_t card_rs_length) const {
|
||||||
|
bool for_young_only_phase = collector_state()->in_young_only_phase();
|
||||||
size_t code_root_rs_length = _analytics->predict_code_root_rs_length(for_young_only_phase);
|
size_t code_root_rs_length = _analytics->predict_code_root_rs_length(for_young_only_phase);
|
||||||
return predict_base_time_ms(pending_cards, card_rs_length, code_root_rs_length);
|
return predict_base_time_ms(pending_cards, card_rs_length, code_root_rs_length);
|
||||||
}
|
}
|
||||||
|
@ -138,6 +138,8 @@ public:
|
|||||||
|
|
||||||
double predict_base_time_ms(size_t pending_cards) const;
|
double predict_base_time_ms(size_t pending_cards) const;
|
||||||
|
|
||||||
|
double predict_base_time_ms(size_t pending_cards, size_t card_rs_length) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Base time contains handling remembered sets and constant other time of the
|
// Base time contains handling remembered sets and constant other time of the
|
||||||
// whole young gen, refinement buffers, and copying survivors.
|
// whole young gen, refinement buffers, and copying survivors.
|
||||||
|
@ -1379,6 +1379,10 @@ public:
|
|||||||
G1ClearBitmapClosure clear(g1h);
|
G1ClearBitmapClosure clear(g1h);
|
||||||
G1CombinedClosure combined(&merge, &clear);
|
G1CombinedClosure combined(&merge, &clear);
|
||||||
|
|
||||||
|
if (_initial_evacuation) {
|
||||||
|
G1HeapRegionRemSet::iterate_for_merge(g1h->young_regions_cardset(), merge);
|
||||||
|
}
|
||||||
|
|
||||||
g1h->collection_set_iterate_increment_from(&combined, nullptr, worker_id);
|
g1h->collection_set_iterate_increment_from(&combined, nullptr, worker_id);
|
||||||
G1MergeCardSetStats stats = merge.stats();
|
G1MergeCardSetStats stats = merge.stats();
|
||||||
|
|
||||||
|
@ -218,15 +218,24 @@ public:
|
|||||||
bool do_heap_region(G1HeapRegion* r) {
|
bool do_heap_region(G1HeapRegion* r) {
|
||||||
G1HeapRegionRemSet* hrrs = r->rem_set();
|
G1HeapRegionRemSet* hrrs = r->rem_set();
|
||||||
|
|
||||||
|
size_t occupied_cards = hrrs->occupied();
|
||||||
// G1HeapRegionRemSet::mem_size() includes the
|
// G1HeapRegionRemSet::mem_size() includes the
|
||||||
// size of the code roots
|
// size of the code roots
|
||||||
size_t rs_unused_mem_sz = hrrs->unused_mem_size();
|
size_t rs_unused_mem_sz = hrrs->unused_mem_size();
|
||||||
size_t rs_mem_sz = hrrs->mem_size();
|
size_t rs_mem_sz = hrrs->mem_size();
|
||||||
|
|
||||||
|
if (r->is_young()) {
|
||||||
|
uint num_young = G1CollectedHeap::heap()->young_regions_count();
|
||||||
|
occupied_cards /= num_young;
|
||||||
|
rs_unused_mem_sz /= num_young;
|
||||||
|
rs_mem_sz /= num_young;
|
||||||
|
}
|
||||||
|
|
||||||
if (rs_mem_sz > _max_rs_mem_sz) {
|
if (rs_mem_sz > _max_rs_mem_sz) {
|
||||||
_max_rs_mem_sz = rs_mem_sz;
|
_max_rs_mem_sz = rs_mem_sz;
|
||||||
_max_rs_mem_sz_region = r;
|
_max_rs_mem_sz_region = r;
|
||||||
}
|
}
|
||||||
size_t occupied_cards = hrrs->occupied();
|
|
||||||
size_t code_root_mem_sz = hrrs->code_roots_mem_size();
|
size_t code_root_mem_sz = hrrs->code_roots_mem_size();
|
||||||
if (code_root_mem_sz > max_code_root_mem_sz()) {
|
if (code_root_mem_sz > max_code_root_mem_sz()) {
|
||||||
_max_code_root_mem_sz = code_root_mem_sz;
|
_max_code_root_mem_sz = code_root_mem_sz;
|
||||||
|
@ -295,10 +295,9 @@ class G1PrepareEvacuationTask : public WorkerTask {
|
|||||||
G1MonotonicArenaMemoryStats _card_set_stats;
|
G1MonotonicArenaMemoryStats _card_set_stats;
|
||||||
|
|
||||||
void sample_card_set_size(G1HeapRegion* hr) {
|
void sample_card_set_size(G1HeapRegion* hr) {
|
||||||
// Sample card set sizes for young gen and humongous before GC: this makes
|
// Sample card set sizes for humongous before GC: this makes the policy to give
|
||||||
// the policy to give back memory to the OS keep the most recent amount of
|
// back memory to the OS keep the most recent amount of memory for these regions.
|
||||||
// memory for these regions.
|
if (hr->is_starts_humongous()) {
|
||||||
if (hr->is_young() || hr->is_starts_humongous()) {
|
|
||||||
_card_set_stats.add(hr->rem_set()->card_set_memory_stats());
|
_card_set_stats.add(hr->rem_set()->card_set_memory_stats());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -507,6 +506,9 @@ void G1YoungCollector::pre_evacuate_collection_set(G1EvacInfo* evacuation_info)
|
|||||||
{
|
{
|
||||||
Ticks start = Ticks::now();
|
Ticks start = Ticks::now();
|
||||||
rem_set()->prepare_for_scan_heap_roots();
|
rem_set()->prepare_for_scan_heap_roots();
|
||||||
|
|
||||||
|
_g1h->prepare_group_cardsets_for_scan();
|
||||||
|
|
||||||
phase_times()->record_prepare_heap_roots_time_ms((Ticks::now() - start).seconds() * 1000.0);
|
phase_times()->record_prepare_heap_roots_time_ms((Ticks::now() - start).seconds() * 1000.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,7 +516,10 @@ void G1YoungCollector::pre_evacuate_collection_set(G1EvacInfo* evacuation_info)
|
|||||||
G1PrepareEvacuationTask g1_prep_task(_g1h);
|
G1PrepareEvacuationTask g1_prep_task(_g1h);
|
||||||
Tickspan task_time = run_task_timed(&g1_prep_task);
|
Tickspan task_time = run_task_timed(&g1_prep_task);
|
||||||
|
|
||||||
_g1h->set_young_gen_card_set_stats(g1_prep_task.all_card_set_stats());
|
G1MonotonicArenaMemoryStats sampled_card_set_stats = g1_prep_task.all_card_set_stats();
|
||||||
|
sampled_card_set_stats.add(_g1h->young_regions_card_set_mm()->memory_stats());
|
||||||
|
_g1h->set_young_gen_card_set_stats(sampled_card_set_stats);
|
||||||
|
|
||||||
_g1h->set_humongous_stats(g1_prep_task.humongous_total(), g1_prep_task.humongous_candidates());
|
_g1h->set_humongous_stats(g1_prep_task.humongous_total(), g1_prep_task.humongous_candidates());
|
||||||
|
|
||||||
phase_times()->record_register_regions(task_time.seconds() * 1000.0);
|
phase_times()->record_register_regions(task_time.seconds() * 1000.0);
|
||||||
|
@ -673,6 +673,10 @@ public:
|
|||||||
|
|
||||||
G1Policy *policy = g1h->policy();
|
G1Policy *policy = g1h->policy();
|
||||||
policy->old_gen_alloc_tracker()->add_allocated_bytes_since_last_gc(_bytes_allocated_in_old_since_last_gc);
|
policy->old_gen_alloc_tracker()->add_allocated_bytes_since_last_gc(_bytes_allocated_in_old_since_last_gc);
|
||||||
|
|
||||||
|
// Add the cards from the group cardsets.
|
||||||
|
_card_rs_length += g1h->young_regions_cardset()->occupied();
|
||||||
|
|
||||||
policy->record_card_rs_length(_card_rs_length);
|
policy->record_card_rs_length(_card_rs_length);
|
||||||
policy->cset_regions_freed();
|
policy->cset_regions_freed();
|
||||||
}
|
}
|
||||||
@ -822,9 +826,10 @@ public:
|
|||||||
JFREventForRegion event(r, _worker_id);
|
JFREventForRegion event(r, _worker_id);
|
||||||
TimerForRegion timer(timer_for_region(r));
|
TimerForRegion timer(timer_for_region(r));
|
||||||
|
|
||||||
stats()->account_card_rs_length(r);
|
|
||||||
|
|
||||||
if (r->is_young()) {
|
if (r->is_young()) {
|
||||||
|
// We only use card_rs_length statistics to estimate young regions length.
|
||||||
|
stats()->account_card_rs_length(r);
|
||||||
assert_tracks_surviving_words(r);
|
assert_tracks_surviving_words(r);
|
||||||
r->record_surv_words_in_group(_surviving_young_words[r->young_index_in_cset()]);
|
r->record_surv_words_in_group(_surviving_young_words[r->young_index_in_cset()]);
|
||||||
}
|
}
|
||||||
@ -911,6 +916,8 @@ public:
|
|||||||
p->record_serial_free_cset_time_ms((Ticks::now() - serial_time).seconds() * 1000.0);
|
p->record_serial_free_cset_time_ms((Ticks::now() - serial_time).seconds() * 1000.0);
|
||||||
|
|
||||||
_g1h->clear_collection_set();
|
_g1h->clear_collection_set();
|
||||||
|
|
||||||
|
_g1h->young_regions_cardset()->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
double worker_cost() const override { return G1CollectedHeap::heap()->collection_set()->region_length(); }
|
double worker_cost() const override { return G1CollectedHeap::heap()->collection_set()->region_length(); }
|
||||||
|
Loading…
Reference in New Issue
Block a user