8265116: ZGC: Steal local stacks instead of flushing them

Co-authored-by: Wang Chao <wchao@openjdk.org>
Reviewed-by: ayang, sjohanss
This commit is contained in:
Per Liden 2021-04-26 11:57:11 +00:00
parent 83364a4b4a
commit 31abe68fa4
4 changed files with 39 additions and 16 deletions

View File

@ -349,17 +349,24 @@ bool ZMark::drain(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks, ZMarkCach
return true;
}
template <typename T>
bool ZMark::drain_and_flush(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks, ZMarkCache* cache, T* timeout) {
const bool success = drain(stripe, stacks, cache, timeout);
bool ZMark::try_steal_local(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks) {
// Try to steal a local stack from another stripe
for (ZMarkStripe* victim_stripe = _stripes.stripe_next(stripe);
victim_stripe != stripe;
victim_stripe = _stripes.stripe_next(victim_stripe)) {
ZMarkStack* const stack = stacks->steal(&_stripes, victim_stripe);
if (stack != NULL) {
// Success, install the stolen stack
stacks->install(&_stripes, stripe, stack);
return true;
}
}
// Flush and publish worker stacks
stacks->flush(&_allocator, &_stripes);
return success;
// Nothing to steal
return false;
}
bool ZMark::try_steal(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks) {
bool ZMark::try_steal_global(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks) {
// Try to steal a stack from another stripe
for (ZMarkStripe* victim_stripe = _stripes.stripe_next(stripe);
victim_stripe != stripe;
@ -376,6 +383,10 @@ bool ZMark::try_steal(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks) {
return false;
}
bool ZMark::try_steal(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks) {
return try_steal_local(stripe, stacks) || try_steal_global(stripe, stacks);
}
void ZMark::idle() const {
os::naked_short_sleep(1);
}
@ -495,7 +506,7 @@ void ZMark::work_without_timeout(ZMarkCache* cache, ZMarkStripe* stripe, ZMarkTh
ZMarkNoTimeout no_timeout;
for (;;) {
drain_and_flush(stripe, stacks, cache, &no_timeout);
drain(stripe, stacks, cache, &no_timeout);
if (try_steal(stripe, stacks)) {
// Stole work
@ -557,7 +568,7 @@ void ZMark::work_with_timeout(ZMarkCache* cache, ZMarkStripe* stripe, ZMarkThrea
ZMarkTimeout timeout(timeout_in_micros);
for (;;) {
if (!drain_and_flush(stripe, stacks, cache, &timeout)) {
if (!drain(stripe, stacks, cache, &timeout)) {
// Timed out
break;
}
@ -583,8 +594,8 @@ void ZMark::work(uint64_t timeout_in_micros) {
work_with_timeout(&cache, stripe, stacks, timeout_in_micros);
}
// Make sure stacks have been flushed
assert(stacks->is_empty(&_stripes), "Should be empty");
// Flush and publish stacks
stacks->flush(&_allocator, &_stripes);
// Free remaining stacks
stacks->free(&_allocator);

View File

@ -71,10 +71,8 @@ private:
ZMarkThreadLocalStacks* stacks,
ZMarkCache* cache,
T* timeout);
template <typename T> bool drain_and_flush(ZMarkStripe* stripe,
ZMarkThreadLocalStacks* stacks,
ZMarkCache* cache,
T* timeout);
bool try_steal_local(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks);
bool try_steal_global(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks);
bool try_steal(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks);
void idle() const;
bool flush(bool at_safepoint);

View File

@ -139,6 +139,9 @@ public:
ZMarkStripe* stripe,
ZMarkStack* stack);
ZMarkStack* steal(ZMarkStripeSet* stripes,
ZMarkStripe* stripe);
bool push(ZMarkStackAllocator* allocator,
ZMarkStripeSet* stripes,
ZMarkStripe* stripe,

View File

@ -219,6 +219,17 @@ inline void ZMarkThreadLocalStacks::install(ZMarkStripeSet* stripes,
*stackp = stack;
}
inline ZMarkStack* ZMarkThreadLocalStacks::steal(ZMarkStripeSet* stripes,
ZMarkStripe* stripe) {
ZMarkStack** const stackp = &_stacks[stripes->stripe_id(stripe)];
ZMarkStack* const stack = *stackp;
if (stack != NULL) {
*stackp = NULL;
}
return stack;
}
inline bool ZMarkThreadLocalStacks::push(ZMarkStackAllocator* allocator,
ZMarkStripeSet* stripes,
ZMarkStripe* stripe,