mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 18:44:38 +02:00
8152101: Move G1 concurrent refinement adjustment code out of G1CollectorPolicy
Reviewed-by: jmasa, jwilhelm, kbarrett
This commit is contained in:
parent
ed7472e0dd
commit
1e047e54c0
4 changed files with 55 additions and 51 deletions
|
@ -27,11 +27,13 @@
|
||||||
#include "gc/g1/concurrentG1RefineThread.hpp"
|
#include "gc/g1/concurrentG1RefineThread.hpp"
|
||||||
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
||||||
#include "gc/g1/g1HotCardCache.hpp"
|
#include "gc/g1/g1HotCardCache.hpp"
|
||||||
|
#include "gc/g1/g1Predictions.hpp"
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
|
|
||||||
ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h) :
|
ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, const G1Predictions* predictor) :
|
||||||
_threads(NULL),
|
_threads(NULL),
|
||||||
_sample_thread(NULL),
|
_sample_thread(NULL),
|
||||||
|
_predictor_sigma(predictor->sigma()),
|
||||||
_hot_card_cache(g1h)
|
_hot_card_cache(g1h)
|
||||||
{
|
{
|
||||||
// Ergonomically select initial concurrent refinement parameters
|
// Ergonomically select initial concurrent refinement parameters
|
||||||
|
@ -49,10 +51,12 @@ ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h) :
|
||||||
FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2);
|
FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2);
|
||||||
}
|
}
|
||||||
set_red_zone(MAX2(G1ConcRefinementRedZone, yellow_zone()));
|
set_red_zone(MAX2(G1ConcRefinementRedZone, yellow_zone()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure, jint* ecode) {
|
ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure, jint* ecode) {
|
||||||
ConcurrentG1Refine* cg1r = new ConcurrentG1Refine(g1h);
|
G1CollectorPolicy* policy = g1h->g1_policy();
|
||||||
|
ConcurrentG1Refine* cg1r = new ConcurrentG1Refine(g1h, &policy->predictor());
|
||||||
if (cg1r == NULL) {
|
if (cg1r == NULL) {
|
||||||
*ecode = JNI_ENOMEM;
|
*ecode = JNI_ENOMEM;
|
||||||
vm_shutdown_during_initialization("Could not create ConcurrentG1Refine");
|
vm_shutdown_during_initialization("Could not create ConcurrentG1Refine");
|
||||||
|
@ -155,3 +159,43 @@ void ConcurrentG1Refine::print_worker_threads_on(outputStream* st) const {
|
||||||
_sample_thread->print_on(st);
|
_sample_thread->print_on(st);
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConcurrentG1Refine::adjust(double update_rs_time,
|
||||||
|
double update_rs_processed_buffers,
|
||||||
|
double goal_ms) {
|
||||||
|
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
|
||||||
|
|
||||||
|
if (G1UseAdaptiveConcRefinement) {
|
||||||
|
const int k_gy = 3, k_gr = 6;
|
||||||
|
const double inc_k = 1.1, dec_k = 0.9;
|
||||||
|
|
||||||
|
size_t g = green_zone();
|
||||||
|
if (update_rs_time > goal_ms) {
|
||||||
|
g = (size_t)(g * dec_k); // Can become 0, that's OK. That would mean a mutator-only processing.
|
||||||
|
} else {
|
||||||
|
if (update_rs_time < goal_ms && update_rs_processed_buffers > g) {
|
||||||
|
g = (size_t)MAX2(g * inc_k, g + 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Change the refinement threads params
|
||||||
|
set_green_zone(g);
|
||||||
|
set_yellow_zone(g * k_gy);
|
||||||
|
set_red_zone(g * k_gr);
|
||||||
|
reinitialize_threads();
|
||||||
|
|
||||||
|
size_t processing_threshold_delta = MAX2<size_t>(green_zone() * _predictor_sigma, 1);
|
||||||
|
size_t processing_threshold = MIN2(green_zone() + processing_threshold_delta,
|
||||||
|
yellow_zone());
|
||||||
|
// Change the barrier params
|
||||||
|
dcqs.set_process_completed_threshold((int)processing_threshold);
|
||||||
|
dcqs.set_max_completed_queue((int)red_zone());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t curr_queue_size = dcqs.completed_buffers_num();
|
||||||
|
if (curr_queue_size >= yellow_zone()) {
|
||||||
|
dcqs.set_completed_queue_padding(curr_queue_size);
|
||||||
|
} else {
|
||||||
|
dcqs.set_completed_queue_padding(0);
|
||||||
|
}
|
||||||
|
dcqs.notify_if_necessary();
|
||||||
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
class ConcurrentG1RefineThread;
|
class ConcurrentG1RefineThread;
|
||||||
class G1CollectedHeap;
|
class G1CollectedHeap;
|
||||||
class G1HotCardCache;
|
class G1HotCardCache;
|
||||||
|
class G1Predictions;
|
||||||
class G1RegionToSpaceMapper;
|
class G1RegionToSpaceMapper;
|
||||||
class G1RemSet;
|
class G1RemSet;
|
||||||
class DirtyCardQueue;
|
class DirtyCardQueue;
|
||||||
|
@ -67,13 +68,15 @@ class ConcurrentG1Refine: public CHeapObj<mtGC> {
|
||||||
|
|
||||||
size_t _thread_threshold_step;
|
size_t _thread_threshold_step;
|
||||||
|
|
||||||
|
double _predictor_sigma;
|
||||||
|
|
||||||
// We delay the refinement of 'hot' cards using the hot card cache.
|
// We delay the refinement of 'hot' cards using the hot card cache.
|
||||||
G1HotCardCache _hot_card_cache;
|
G1HotCardCache _hot_card_cache;
|
||||||
|
|
||||||
// Reset the threshold step value based of the current zone boundaries.
|
// Reset the threshold step value based of the current zone boundaries.
|
||||||
void reset_threshold_step();
|
void reset_threshold_step();
|
||||||
|
|
||||||
ConcurrentG1Refine(G1CollectedHeap* g1h);
|
ConcurrentG1Refine(G1CollectedHeap* g1h, const G1Predictions* predictions);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~ConcurrentG1Refine();
|
~ConcurrentG1Refine();
|
||||||
|
@ -85,6 +88,8 @@ class ConcurrentG1Refine: public CHeapObj<mtGC> {
|
||||||
void init(G1RegionToSpaceMapper* card_counts_storage);
|
void init(G1RegionToSpaceMapper* card_counts_storage);
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
void adjust(double update_rs_time, double update_rs_processed_buffers, double goal_ms);
|
||||||
|
|
||||||
void reinitialize_threads();
|
void reinitialize_threads();
|
||||||
|
|
||||||
// Iterate over all concurrent refinement threads
|
// Iterate over all concurrent refinement threads
|
||||||
|
|
|
@ -878,9 +878,9 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t
|
||||||
} else {
|
} else {
|
||||||
update_rs_time_goal_ms -= scan_hcc_time_ms;
|
update_rs_time_goal_ms -= scan_hcc_time_ms;
|
||||||
}
|
}
|
||||||
adjust_concurrent_refinement(average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms,
|
_g1->concurrent_g1_refine()->adjust(average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms,
|
||||||
phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS),
|
phase_times()->sum_thread_work_items(G1GCPhaseTimes::UpdateRS),
|
||||||
update_rs_time_goal_ms);
|
update_rs_time_goal_ms);
|
||||||
|
|
||||||
cset_chooser()->verify();
|
cset_chooser()->verify();
|
||||||
}
|
}
|
||||||
|
@ -942,47 +942,6 @@ void G1CollectorPolicy::print_phases() {
|
||||||
phase_times()->print();
|
phase_times()->print();
|
||||||
}
|
}
|
||||||
|
|
||||||
void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time,
|
|
||||||
double update_rs_processed_buffers,
|
|
||||||
double goal_ms) {
|
|
||||||
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
|
|
||||||
ConcurrentG1Refine *cg1r = G1CollectedHeap::heap()->concurrent_g1_refine();
|
|
||||||
|
|
||||||
if (G1UseAdaptiveConcRefinement) {
|
|
||||||
const int k_gy = 3, k_gr = 6;
|
|
||||||
const double inc_k = 1.1, dec_k = 0.9;
|
|
||||||
|
|
||||||
size_t g = cg1r->green_zone();
|
|
||||||
if (update_rs_time > goal_ms) {
|
|
||||||
g = (size_t)(g * dec_k); // Can become 0, that's OK. That would mean a mutator-only processing.
|
|
||||||
} else {
|
|
||||||
if (update_rs_time < goal_ms && update_rs_processed_buffers > g) {
|
|
||||||
g = (size_t)MAX2(g * inc_k, g + 1.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Change the refinement threads params
|
|
||||||
cg1r->set_green_zone(g);
|
|
||||||
cg1r->set_yellow_zone(g * k_gy);
|
|
||||||
cg1r->set_red_zone(g * k_gr);
|
|
||||||
cg1r->reinitialize_threads();
|
|
||||||
|
|
||||||
size_t processing_threshold_delta = MAX2<size_t>(cg1r->green_zone() * _predictor.sigma(), 1);
|
|
||||||
size_t processing_threshold = MIN2(cg1r->green_zone() + processing_threshold_delta,
|
|
||||||
cg1r->yellow_zone());
|
|
||||||
// Change the barrier params
|
|
||||||
dcqs.set_process_completed_threshold((int)processing_threshold);
|
|
||||||
dcqs.set_max_completed_queue((int)cg1r->red_zone());
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t curr_queue_size = dcqs.completed_buffers_num();
|
|
||||||
if (curr_queue_size >= cg1r->yellow_zone()) {
|
|
||||||
dcqs.set_completed_queue_padding(curr_queue_size);
|
|
||||||
} else {
|
|
||||||
dcqs.set_completed_queue_padding(0);
|
|
||||||
}
|
|
||||||
dcqs.notify_if_necessary();
|
|
||||||
}
|
|
||||||
|
|
||||||
double G1CollectorPolicy::predict_yg_surv_rate(int age, SurvRateGroup* surv_rate_group) const {
|
double G1CollectorPolicy::predict_yg_surv_rate(int age, SurvRateGroup* surv_rate_group) const {
|
||||||
TruncatedSeq* seq = surv_rate_group->get_seq(age);
|
TruncatedSeq* seq = surv_rate_group->get_seq(age);
|
||||||
guarantee(seq->num() > 0, "There should be some young gen survivor samples available. Tried to access with age %d", age);
|
guarantee(seq->num() > 0, "There should be some young gen survivor samples available. Tried to access with age %d", age);
|
||||||
|
|
|
@ -91,10 +91,6 @@ class G1CollectorPolicy: public CollectorPolicy {
|
||||||
bool verify_young_ages(HeapRegion* head, SurvRateGroup *surv_rate_group);
|
bool verify_young_ages(HeapRegion* head, SurvRateGroup *surv_rate_group);
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
||||||
void adjust_concurrent_refinement(double update_rs_time,
|
|
||||||
double update_rs_processed_buffers,
|
|
||||||
double goal_ms);
|
|
||||||
|
|
||||||
double _pause_time_target_ms;
|
double _pause_time_target_ms;
|
||||||
|
|
||||||
size_t _pending_cards;
|
size_t _pending_cards;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue