From patchwork Mon Jul 26 12:59:55 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [gccgo] When a goroutine exits, free its mcache Date: Mon, 26 Jul 2010 02:59:55 -0000 From: Ian Taylor X-Patchwork-Id: 59911 Message-Id: To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com In the gc compiler runtime, goroutines exit but OS threads never do. This means that there is never a need to free the thread-specific memory cache. In gccgo, OS threads do exit. And that means that we do need to free the thread-specific cache when they exit. That is what this patch does. Interestingly, the garbage collector is fully able to free up all the memory used by the cache. However, it is not able to free the cache itself. This means that caches slowly accumulate over time as a new one is allocated for each new goroutine. A more important effect is that each cache holds references to spans. Not freeing the caches means that the spans are never freed. And that means that the spans are during each garbage collection sweep, even though they no longer contain any allocated memory. Fixing this problem speeds up gccgo's garbage collection to take an acceptable amount of time. Committed to gccgo branch. Ian diff -r 4ccd6253e3e9 libgo/runtime/go-go.c --- a/libgo/runtime/go-go.c Mon Jul 26 04:21:01 2010 -0700 +++ b/libgo/runtime/go-go.c Mon Jul 26 05:47:38 2010 -0700 @@ -114,6 +114,11 @@ free (list_entry); m->list_entry = NULL; + + MCache_ReleaseAll (m->mcache); + __builtin_memset (m->mcache, 0, sizeof (struct MCache)); + FixAlloc_Free (&mheap.cachealloc, m->mcache); + m->mcache = NULL; } /* Start the thread. */ @@ -511,7 +516,7 @@ struct __go_thread_id *p; for (p = __go_all_thread_ids; p != NULL; p = p->next) - MCache_ReleaseAll(p->m->mcache); + MCache_ReleaseAll (p->m->mcache); } /* Start the other threads after garbage collection. */ diff -r 4ccd6253e3e9 libgo/runtime/malloc.goc --- a/libgo/runtime/malloc.goc Mon Jul 26 04:21:01 2010 -0700 +++ b/libgo/runtime/malloc.goc Mon Jul 26 05:47:38 2010 -0700 @@ -248,6 +248,10 @@ MCache *c; c = FixAlloc_Alloc(&mheap.cachealloc); + + // Clear the free list used by FixAlloc; assume the rest is zeroed. + c->list[0].list = nil; + mstats.mcache_inuse = mheap.cachealloc.inuse; mstats.mcache_sys = mheap.cachealloc.sys; return c;