8247593: Shenandoah: should not block pacing reporters

Reviewed-by: rkennke
This commit is contained in:
Aleksey Shipilev 2020-06-17 09:43:16 +02:00
parent 6d2959b393
commit aeeaffa888
5 changed files with 41 additions and 15 deletions

View file

@ -53,6 +53,9 @@ ShenandoahControlThread::ShenandoahControlThread() :
create_and_start(ShenandoahCriticalControlThreadPriority ? CriticalPriority : NearMaxPriority); create_and_start(ShenandoahCriticalControlThreadPriority ? CriticalPriority : NearMaxPriority);
_periodic_task.enroll(); _periodic_task.enroll();
_periodic_satb_flush_task.enroll(); _periodic_satb_flush_task.enroll();
if (ShenandoahPacing) {
_periodic_pacer_notify_task.enroll();
}
} }
ShenandoahControlThread::~ShenandoahControlThread() { ShenandoahControlThread::~ShenandoahControlThread() {
@ -68,6 +71,11 @@ void ShenandoahPeriodicSATBFlushTask::task() {
ShenandoahHeap::heap()->force_satb_flush_all_threads(); ShenandoahHeap::heap()->force_satb_flush_all_threads();
} }
void ShenandoahPeriodicPacerNotify::task() {
assert(ShenandoahPacing, "Should not be here otherwise");
ShenandoahHeap::heap()->pacer()->notify_waiters();
}
void ShenandoahControlThread::run_service() { void ShenandoahControlThread::run_service() {
ShenandoahHeap* heap = ShenandoahHeap::heap(); ShenandoahHeap* heap = ShenandoahHeap::heap();

View file

@ -52,6 +52,13 @@ public:
virtual void task(); virtual void task();
}; };
// Periodic task to notify blocked paced waiters.
class ShenandoahPeriodicPacerNotify : public PeriodicTask {
public:
ShenandoahPeriodicPacerNotify() : PeriodicTask(PeriodicTask::min_interval) {}
virtual void task();
};
class ShenandoahControlThread: public ConcurrentGCThread { class ShenandoahControlThread: public ConcurrentGCThread {
friend class VMStructs; friend class VMStructs;
@ -70,6 +77,7 @@ private:
Monitor _gc_waiters_lock; Monitor _gc_waiters_lock;
ShenandoahPeriodicTask _periodic_task; ShenandoahPeriodicTask _periodic_task;
ShenandoahPeriodicSATBFlushTask _periodic_satb_flush_task; ShenandoahPeriodicSATBFlushTask _periodic_satb_flush_task;
ShenandoahPeriodicPacerNotify _periodic_pacer_notify_task;
public: public:
void run_service(); void run_service();

View file

@ -193,7 +193,7 @@ void ShenandoahPacer::restart_with(size_t non_taxable_bytes, double tax_rate) {
Atomic::inc(&_epoch); Atomic::inc(&_epoch);
// Shake up stalled waiters after budget update. // Shake up stalled waiters after budget update.
notify_waiters(); _need_notify_waiters.try_set();
} }
bool ShenandoahPacer::claim_for_alloc(size_t words, bool force) { bool ShenandoahPacer::claim_for_alloc(size_t words, bool force) {
@ -222,8 +222,8 @@ void ShenandoahPacer::unpace_for_alloc(intptr_t epoch, size_t words) {
return; return;
} }
intptr_t tax = MAX2<intptr_t>(1, words * Atomic::load(&_tax_rate)); size_t tax = MAX2<size_t>(1, words * Atomic::load(&_tax_rate));
Atomic::add(&_budget, tax); add_budget(tax);
} }
intptr_t ShenandoahPacer::epoch() { intptr_t ShenandoahPacer::epoch() {
@ -288,8 +288,10 @@ void ShenandoahPacer::wait(size_t time_ms) {
} }
void ShenandoahPacer::notify_waiters() { void ShenandoahPacer::notify_waiters() {
if (_need_notify_waiters.try_unset()) {
MonitorLocker locker(_wait_monitor); MonitorLocker locker(_wait_monitor);
_wait_monitor->notify_all(); _wait_monitor->notify_all();
}
} }
void ShenandoahPacer::print_on(outputStream* out) const { void ShenandoahPacer::print_on(outputStream* out) const {

View file

@ -46,6 +46,7 @@ private:
BinaryMagnitudeSeq _delays; BinaryMagnitudeSeq _delays;
TruncatedSeq* _progress_history; TruncatedSeq* _progress_history;
Monitor* _wait_monitor; Monitor* _wait_monitor;
ShenandoahSharedFlag _need_notify_waiters;
// Set once per phase // Set once per phase
volatile intptr_t _epoch; volatile intptr_t _epoch;
@ -89,6 +90,8 @@ public:
void pace_for_alloc(size_t words); void pace_for_alloc(size_t words);
void unpace_for_alloc(intptr_t epoch, size_t words); void unpace_for_alloc(intptr_t epoch, size_t words);
void notify_waiters();
intptr_t epoch(); intptr_t epoch();
void print_on(outputStream* out) const; void print_on(outputStream* out) const;
@ -97,12 +100,12 @@ private:
inline void report_internal(size_t words); inline void report_internal(size_t words);
inline void report_progress_internal(size_t words); inline void report_progress_internal(size_t words);
inline void add_budget(size_t words);
void restart_with(size_t non_taxable_bytes, double tax_rate); void restart_with(size_t non_taxable_bytes, double tax_rate);
size_t update_and_get_progress_history(); size_t update_and_get_progress_history();
void wait(size_t time_ms); void wait(size_t time_ms);
void notify_waiters();
}; };
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHPACER_HPP #endif // SHARE_GC_SHENANDOAH_SHENANDOAHPACER_HPP

View file

@ -47,15 +47,7 @@ inline void ShenandoahPacer::report_alloc(size_t words) {
inline void ShenandoahPacer::report_internal(size_t words) { inline void ShenandoahPacer::report_internal(size_t words) {
assert(ShenandoahPacing, "Only be here when pacing is enabled"); assert(ShenandoahPacing, "Only be here when pacing is enabled");
STATIC_ASSERT(sizeof(size_t) <= sizeof(intptr_t)); add_budget(words);
intptr_t inc = (intptr_t) words;
intptr_t new_budget = Atomic::add(&_budget, inc);
// Was the budget replenished beyond zero? Then all pacing claims
// are satisfied, notify the waiters.
if (new_budget >= 0 && (new_budget - inc) < 0) {
notify_waiters();
}
} }
inline void ShenandoahPacer::report_progress_internal(size_t words) { inline void ShenandoahPacer::report_progress_internal(size_t words) {
@ -64,4 +56,17 @@ inline void ShenandoahPacer::report_progress_internal(size_t words) {
Atomic::add(&_progress, (intptr_t)words); Atomic::add(&_progress, (intptr_t)words);
} }
inline void ShenandoahPacer::add_budget(size_t words) {
STATIC_ASSERT(sizeof(size_t) <= sizeof(intptr_t));
intptr_t inc = (intptr_t) words;
intptr_t new_budget = Atomic::add(&_budget, inc);
// Was the budget replenished beyond zero? Then all pacing claims
// are satisfied, notify the waiters. Avoid taking any locks here,
// as it can be called from hot paths and/or while holding other locks.
if (new_budget >= 0 && (new_budget - inc) < 0) {
_need_notify_waiters.try_set();
}
}
#endif // SHARE_GC_SHENANDOAH_SHENANDOAHPACER_INLINE_HPP #endif // SHARE_GC_SHENANDOAH_SHENANDOAHPACER_INLINE_HPP