mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-08 17:38:38 +00:00
6976060: G1: humongous object allocations should initiate marking cycles when necessary
Reviewed-by: tonyp, johnc
This commit is contained in:
parent
af0211c200
commit
c11ba93098
@ -1045,19 +1045,26 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size,
|
||||
// regions, we'll first try to do the allocation without doing a
|
||||
// collection hoping that there's enough space in the heap.
|
||||
result = humongous_obj_allocate(word_size);
|
||||
if (result != NULL) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (GC_locker::is_active_and_needs_gc()) {
|
||||
should_try_gc = false;
|
||||
} else {
|
||||
// Read the GC count while still holding the Heap_lock.
|
||||
gc_count_before = SharedHeap::heap()->total_collections();
|
||||
should_try_gc = true;
|
||||
if (result == NULL) {
|
||||
if (GC_locker::is_active_and_needs_gc()) {
|
||||
should_try_gc = false;
|
||||
} else {
|
||||
// Read the GC count while still holding the Heap_lock.
|
||||
gc_count_before = SharedHeap::heap()->total_collections();
|
||||
should_try_gc = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result != NULL) {
|
||||
if (g1_policy()->need_to_start_conc_mark("concurrent humongous allocation")) {
|
||||
// We need to release the Heap_lock before we try to call collect
|
||||
collect(GCCause::_g1_humongous_allocation);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (should_try_gc) {
|
||||
// If we failed to allocate the humongous object, we should try to
|
||||
// do a collection pause (if we're allowed) in case it reclaims
|
||||
@ -1111,7 +1118,11 @@ HeapWord* G1CollectedHeap::attempt_allocation_at_safepoint(size_t word_size,
|
||||
return _mutator_alloc_region.attempt_allocation_locked(word_size,
|
||||
false /* bot_updates */);
|
||||
} else {
|
||||
return humongous_obj_allocate(word_size);
|
||||
HeapWord* result = humongous_obj_allocate(word_size);
|
||||
if (result != NULL && g1_policy()->need_to_start_conc_mark("STW humongous allocation")) {
|
||||
g1_policy()->set_initiate_conc_mark_if_possible();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ShouldNotReachHere();
|
||||
@ -2295,7 +2306,8 @@ size_t G1CollectedHeap::unsafe_max_alloc() {
|
||||
bool G1CollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
|
||||
return
|
||||
((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||
|
||||
(cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent));
|
||||
(cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent) ||
|
||||
cause == GCCause::_g1_humongous_allocation);
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
||||
@ -355,6 +355,7 @@ private:
|
||||
// explicitly started if:
|
||||
// (a) cause == _gc_locker and +GCLockerInvokesConcurrent, or
|
||||
// (b) cause == _java_lang_system_gc and +ExplicitGCInvokesConcurrent.
|
||||
// (c) cause == _g1_humongous_allocation
|
||||
bool should_do_concurrent_full_gc(GCCause::Cause cause);
|
||||
|
||||
// Keeps track of how many "full collections" (i.e., Full GCs or
|
||||
@ -1172,6 +1173,10 @@ public:
|
||||
_old_set.remove(hr);
|
||||
}
|
||||
|
||||
size_t non_young_capacity_bytes() {
|
||||
return _old_set.total_capacity_bytes() + _humongous_set.total_capacity_bytes();
|
||||
}
|
||||
|
||||
void set_free_regions_coming();
|
||||
void reset_free_regions_coming();
|
||||
bool free_regions_coming() { return _free_regions_coming; }
|
||||
|
||||
@ -213,8 +213,6 @@ G1CollectorPolicy::G1CollectorPolicy() :
|
||||
_survivor_bytes_before_gc(0),
|
||||
_capacity_before_gc(0),
|
||||
|
||||
_prev_collection_pause_used_at_end_bytes(0),
|
||||
|
||||
_eden_cset_region_length(0),
|
||||
_survivor_cset_region_length(0),
|
||||
_old_cset_region_length(0),
|
||||
@ -1140,6 +1138,45 @@ double G1CollectorPolicy::max_sum(double* data1, double* data2) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool G1CollectorPolicy::need_to_start_conc_mark(const char* source) {
|
||||
if (_g1->mark_in_progress()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t marking_initiating_used_threshold =
|
||||
(_g1->capacity() / 100) * InitiatingHeapOccupancyPercent;
|
||||
size_t cur_used_bytes = _g1->non_young_capacity_bytes();
|
||||
|
||||
if (cur_used_bytes > marking_initiating_used_threshold) {
|
||||
if (gcs_are_young()) {
|
||||
ergo_verbose4(ErgoConcCycles,
|
||||
"request concurrent cycle initiation",
|
||||
ergo_format_reason("occupancy higher than threshold")
|
||||
ergo_format_byte("occupancy")
|
||||
ergo_format_byte_perc("threshold")
|
||||
ergo_format_str("source"),
|
||||
cur_used_bytes,
|
||||
marking_initiating_used_threshold,
|
||||
(double) InitiatingHeapOccupancyPercent,
|
||||
source);
|
||||
return true;
|
||||
} else {
|
||||
ergo_verbose4(ErgoConcCycles,
|
||||
"do not request concurrent cycle initiation",
|
||||
ergo_format_reason("still doing mixed collections")
|
||||
ergo_format_byte("occupancy")
|
||||
ergo_format_byte_perc("threshold")
|
||||
ergo_format_str("source"),
|
||||
cur_used_bytes,
|
||||
marking_initiating_used_threshold,
|
||||
(double) InitiatingHeapOccupancyPercent,
|
||||
source);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Anything below that is considered to be zero
|
||||
#define MIN_TIMER_GRANULARITY 0.0000001
|
||||
|
||||
@ -1166,44 +1203,16 @@ void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
|
||||
#endif // PRODUCT
|
||||
|
||||
last_pause_included_initial_mark = during_initial_mark_pause();
|
||||
if (last_pause_included_initial_mark)
|
||||
if (last_pause_included_initial_mark) {
|
||||
record_concurrent_mark_init_end(0.0);
|
||||
|
||||
size_t marking_initiating_used_threshold =
|
||||
(_g1->capacity() / 100) * InitiatingHeapOccupancyPercent;
|
||||
|
||||
if (!_g1->mark_in_progress() && !_last_young_gc) {
|
||||
assert(!last_pause_included_initial_mark, "invariant");
|
||||
if (cur_used_bytes > marking_initiating_used_threshold) {
|
||||
if (cur_used_bytes > _prev_collection_pause_used_at_end_bytes) {
|
||||
assert(!during_initial_mark_pause(), "we should not see this here");
|
||||
|
||||
ergo_verbose3(ErgoConcCycles,
|
||||
"request concurrent cycle initiation",
|
||||
ergo_format_reason("occupancy higher than threshold")
|
||||
ergo_format_byte("occupancy")
|
||||
ergo_format_byte_perc("threshold"),
|
||||
cur_used_bytes,
|
||||
marking_initiating_used_threshold,
|
||||
(double) InitiatingHeapOccupancyPercent);
|
||||
|
||||
// Note: this might have already been set, if during the last
|
||||
// pause we decided to start a cycle but at the beginning of
|
||||
// this pause we decided to postpone it. That's OK.
|
||||
set_initiate_conc_mark_if_possible();
|
||||
} else {
|
||||
ergo_verbose2(ErgoConcCycles,
|
||||
"do not request concurrent cycle initiation",
|
||||
ergo_format_reason("occupancy lower than previous occupancy")
|
||||
ergo_format_byte("occupancy")
|
||||
ergo_format_byte("previous occupancy"),
|
||||
cur_used_bytes,
|
||||
_prev_collection_pause_used_at_end_bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_prev_collection_pause_used_at_end_bytes = cur_used_bytes;
|
||||
if (!_last_young_gc && need_to_start_conc_mark("end of GC")) {
|
||||
// Note: this might have already been set, if during the last
|
||||
// pause we decided to start a cycle but at the beginning of
|
||||
// this pause we decided to postpone it. That's OK.
|
||||
set_initiate_conc_mark_if_possible();
|
||||
}
|
||||
|
||||
_mmu_tracker->add_pause(end_time_sec - elapsed_ms/1000.0,
|
||||
end_time_sec, false);
|
||||
|
||||
@ -177,7 +177,6 @@ private:
|
||||
double _cur_collection_start_sec;
|
||||
size_t _cur_collection_pause_used_at_start_bytes;
|
||||
size_t _cur_collection_pause_used_regions_at_start;
|
||||
size_t _prev_collection_pause_used_at_end_bytes;
|
||||
double _cur_collection_par_time_ms;
|
||||
double _cur_satb_drain_time_ms;
|
||||
double _cur_clear_ct_time_ms;
|
||||
@ -800,6 +799,8 @@ public:
|
||||
|
||||
GenRemSet::Name rem_set_name() { return GenRemSet::CardTable; }
|
||||
|
||||
bool need_to_start_conc_mark(const char* source);
|
||||
|
||||
// Update the heuristic info to record a collection pause of the given
|
||||
// start time, where the given number of bytes were used at the start.
|
||||
// This may involve changing the desired size of a collection set.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2012, 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
|
||||
@ -74,8 +74,9 @@ void VM_G1IncCollectionPause::doit() {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
assert(!_should_initiate_conc_mark ||
|
||||
((_gc_cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||
|
||||
(_gc_cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)),
|
||||
"only a GC locker or a System.gc() induced GC should start a cycle");
|
||||
(_gc_cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent) ||
|
||||
_gc_cause == GCCause::_g1_humongous_allocation),
|
||||
"only a GC locker, a System.gc() or a hum allocation induced GC should start a cycle");
|
||||
|
||||
if (_word_size > 0) {
|
||||
// An allocation has been requested. So, try to do that first.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2012, 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
|
||||
@ -84,6 +84,9 @@ const char* GCCause::to_string(GCCause::Cause cause) {
|
||||
case _g1_inc_collection_pause:
|
||||
return "G1 Evacuation Pause";
|
||||
|
||||
case _g1_humongous_allocation:
|
||||
return "G1 Humongous Allocation";
|
||||
|
||||
case _last_ditch_collection:
|
||||
return "Last ditch collection";
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2012, 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
|
||||
@ -66,6 +66,7 @@ class GCCause : public AllStatic {
|
||||
_adaptive_size_policy,
|
||||
|
||||
_g1_inc_collection_pause,
|
||||
_g1_humongous_allocation,
|
||||
|
||||
_last_ditch_collection,
|
||||
_last_gc_cause
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user