< prev index next >
src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp
Print this page
rev 59715 : 8247358: Shenandoah: reconsider free budget slice for marking
Reviewed-by: XXX
rev 59716 : 8247367: Shenandoah: pacer should wait on lock instead of exponential backoff
Reviewed-by: XXX
@@ -189,10 +189,13 @@
size_t initial = (size_t)(non_taxable_bytes * tax_rate) >> LogHeapWordSize;
STATIC_ASSERT(sizeof(size_t) <= sizeof(intptr_t));
Atomic::xchg(&_budget, (intptr_t)initial);
Atomic::store(&_tax_rate, tax_rate);
Atomic::inc(&_epoch);
+
+ // Shake up stalled waiters after budget update.
+ notify_waiters();
}
bool ShenandoahPacer::claim_for_alloc(size_t words, bool force) {
assert(ShenandoahPacing, "Only be here when pacing is enabled");
@@ -229,60 +232,49 @@
void ShenandoahPacer::pace_for_alloc(size_t words) {
assert(ShenandoahPacing, "Only be here when pacing is enabled");
// Fast path: try to allocate right away
- if (claim_for_alloc(words, false)) {
+ bool claimed = claim_for_alloc(words, false);
+ if (claimed) {
return;
}
+ // Forcefully claim the budget: it may go negative at this point, and
+ // GC should replenish for this and subsequent allocations. After this claim,
+ // we would wait a bit until our claim is matched by additional progress,
+ // or the time budget depletes.
+ claimed = claim_for_alloc(words, true);
+ assert(claimed, "Should always succeed");
+
// Threads that are attaching should not block at all: they are not
// fully initialized yet. Blocking them would be awkward.
// This is probably the path that allocates the thread oop itself.
- // Forcefully claim without waiting.
if (JavaThread::current()->is_attaching_via_jni()) {
- claim_for_alloc(words, true);
return;
}
- size_t max = ShenandoahPacingMaxDelay;
double start = os::elapsedTime();
- size_t total = 0;
- size_t cur = 0;
+ size_t max_ms = ShenandoahPacingMaxDelay;
+ size_t total_ms = 0;
while (true) {
// We could instead assist GC, but this would suffice for now.
- // This code should also participate in safepointing.
- // Perform the exponential backoff, limited by max.
-
- cur = cur * 2;
- if (total + cur > max) {
- cur = (max > total) ? (max - total) : 0;
- }
- cur = MAX2<size_t>(1, cur);
-
- wait(cur);
+ size_t cur_ms = (max_ms > total_ms) ? (max_ms - total_ms) : 1;
+ wait(cur_ms);
double end = os::elapsedTime();
- total = (size_t)((end - start) * 1000);
-
- if (total > max) {
- // Spent local time budget to wait for enough GC progress.
- // Breaking out and allocating anyway, which may mean we outpace GC,
- // and start Degenerated GC cycle.
- _delays.add(total);
-
- // Forcefully claim the budget: it may go negative at this point, and
- // GC should replenish for this and subsequent allocations
- claim_for_alloc(words, true);
- break;
- }
+ total_ms = (size_t)((end - start) * 1000);
- if (claim_for_alloc(words, false)) {
- // Acquired enough permit, nice. Can allocate now.
- _delays.add(total);
+ if (total_ms > max_ms || Atomic::load(&_budget) >= 0) {
+ // Exiting if either:
+ // a) Spent local time budget to wait for enough GC progress.
+ // Breaking out and allocating anyway, which may mean we outpace GC,
+ // and start Degenerated GC cycle.
+ // b) The budget had been replenished, which means our claim is satisfied.
+ _delays.add(total_ms);
break;
}
}
}
< prev index next >