mirror of
https://github.com/golang/go
synced 2024-11-19 06:24:41 -07:00
runtime: cache one GC workbuf in thread-local storage
We call scanblock for lots of small root pieces e.g. for every stack frame args and locals area. Every scanblock invocation calls getempty/putempty, which accesses lock-free stack shared among all worker threads. One-element local cache allows most scanblock calls to proceed without accessing the shared stack. LGTM=rsc R=golang-codereviews, rlh CC=golang-codereviews, khr, rsc https://golang.org/cl/121250043
This commit is contained in:
parent
22e08d1a3b
commit
f6f2f77142
@ -334,6 +334,8 @@ struct MCache
|
||||
|
||||
StackFreeList stackcache[NumStackOrders];
|
||||
|
||||
void* gcworkbuf;
|
||||
|
||||
// Local allocator stats, flushed during GC.
|
||||
uintptr local_nlookup; // number of pointer lookups
|
||||
uintptr local_largefree; // bytes freed for large objects (>MaxSmallSize)
|
||||
@ -344,6 +346,7 @@ struct MCache
|
||||
MSpan* runtime·MCache_Refill(MCache *c, int32 sizeclass);
|
||||
void runtime·MCache_ReleaseAll(MCache *c);
|
||||
void runtime·stackcache_clear(MCache *c);
|
||||
void runtime·gcworkbuffree(void *b);
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -44,6 +44,7 @@ freemcache(MCache *c)
|
||||
{
|
||||
runtime·MCache_ReleaseAll(c);
|
||||
runtime·stackcache_clear(c);
|
||||
runtime·gcworkbuffree(c->gcworkbuf);
|
||||
runtime·lock(&runtime·mheap);
|
||||
runtime·purgecachedstats(c);
|
||||
runtime·FixAlloc_Free(&runtime·mheap.cachealloc, c);
|
||||
|
@ -570,8 +570,17 @@ markroot(ParFor *desc, uint32 i)
|
||||
static Workbuf*
|
||||
getempty(Workbuf *b)
|
||||
{
|
||||
MCache *c;
|
||||
|
||||
if(b != nil)
|
||||
runtime·lfstackpush(&work.full, &b->node);
|
||||
b = nil;
|
||||
c = g->m->mcache;
|
||||
if(c->gcworkbuf != nil) {
|
||||
b = c->gcworkbuf;
|
||||
c->gcworkbuf = nil;
|
||||
}
|
||||
if(b == nil)
|
||||
b = (Workbuf*)runtime·lfstackpop(&work.empty);
|
||||
if(b == nil)
|
||||
b = runtime·persistentalloc(sizeof(*b), CacheLineSize, &mstats.gc_sys);
|
||||
@ -582,9 +591,23 @@ getempty(Workbuf *b)
|
||||
static void
|
||||
putempty(Workbuf *b)
|
||||
{
|
||||
MCache *c;
|
||||
|
||||
c = g->m->mcache;
|
||||
if(c->gcworkbuf == nil) {
|
||||
c->gcworkbuf = b;
|
||||
return;
|
||||
}
|
||||
runtime·lfstackpush(&work.empty, &b->node);
|
||||
}
|
||||
|
||||
void
|
||||
runtime·gcworkbuffree(void *b)
|
||||
{
|
||||
if(b != nil)
|
||||
putempty(b);
|
||||
}
|
||||
|
||||
// Get a full work buffer off the work.full list, or return nil.
|
||||
static Workbuf*
|
||||
getfull(Workbuf *b)
|
||||
|
Loading…
Reference in New Issue
Block a user