Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(330)

Unified Diff: src/pkg/runtime/mheap.c

Issue 5451057: code review 5451057: runtime: release unused memory to the OS. (Closed)
Patch Set: diff -r fae148fab2a7 https://code.google.com/p/go/ Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/pkg/runtime/mgc0.c ('k') | src/pkg/runtime/proc.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pkg/runtime/mheap.c
===================================================================
--- a/src/pkg/runtime/mheap.c
+++ b/src/pkg/runtime/mheap.c
@@ -103,6 +103,8 @@
runtime·MSpanList_Remove(s);
s->state = MSpanInUse;
mstats.heap_idle -= s->npages<<PageShift;
+ mstats.heap_released -= s->npreleased<<PageShift;
+ s->npreleased = 0;
if(s->npages > npage) {
// Trim extra and put it back in the heap.
@@ -280,6 +282,8 @@
}
mstats.heap_idle += s->npages<<PageShift;
s->state = MSpanFree;
+ s->unusedsince = 0;
+ s->npreleased = 0;
runtime·MSpanList_Remove(s);
sp = (uintptr*)(s->start<<PageShift);
@@ -292,6 +296,7 @@
*tp |= *sp; // propagate "needs zeroing" mark
s->start = t->start;
s->npages += t->npages;
+ s->npreleased = t->npreleased; // absorb released pages
p -= t->npages;
h->map[p] = s;
runtime·MSpanList_Remove(t);
@@ -304,6 +309,7 @@
tp = (uintptr*)(t->start<<PageShift);
*sp |= *tp; // propagate "needs zeroing" mark
s->npages += t->npages;
+ s->npreleased += t->npreleased;
h->map[p + s->npages - 1] = s;
runtime·MSpanList_Remove(t);
t->state = MSpanDead;
@@ -317,8 +323,81 @@
runtime·MSpanList_Insert(&h->free[s->npages], s);
else
runtime·MSpanList_Insert(&h->large, s);
+}
- // TODO(rsc): IncrementalScavenge() to return memory to OS.
+// Release (part of) unused memory to OS.
+// Goroutine created in runtime·schedinit.
+// Loop forever.
+void
+runtime·MHeap_Scavenger(void)
+{
+ MHeap *h;
+ MSpan *s, *list;
+ uint64 tick, now, forcegc, limit;
+ uint32 k, i;
+ uintptr released, sumreleased;
+ byte *env;
+ bool trace;
+ Note note;
+
+ // If we go two minutes without a garbage collection, force one to run.
+ forcegc = 2*60*1e9;
+ // If a span goes unused for 5 minutes after a garbage collection,
+ // we hand it back to the operating system.
+ limit = 5*60*1e9;
+ // Make wake-up period small enough for the sampling to be correct.
+ tick = forcegc < limit ? forcegc/2 : limit/2;
+
+ trace = false;
+ env = runtime·getenv("GOGCTRACE");
+ if(env != nil)
+ trace = runtime·atoi(env) > 0;
+
+ h = &runtime·mheap;
+ for(k=0;; k++) {
+ runtime·noteclear(&note);
+ runtime·entersyscall();
+ runtime·notetsleep(&note, tick);
+ runtime·exitsyscall();
+
+ runtime·lock(h);
+ now = runtime·nanotime();
+ if(now - mstats.last_gc > forcegc) {
+ runtime·unlock(h);
+ runtime·gc(1);
+ runtime·lock(h);
+ now = runtime·nanotime();
+ if (trace)
+ runtime·printf("scvg%d: GC forced\n", k);
+ }
+ sumreleased = 0;
+ for(i=0; i < nelem(h->free)+1; i++) {
+ if(i < nelem(h->free))
+ list = &h->free[i];
+ else
+ list = &h->large;
+ if(runtime·MSpanList_IsEmpty(list))
+ continue;
+ for(s=list->next; s != list; s=s->next) {
+ if(s->unusedsince != 0 && (now - s->unusedsince) > limit) {
+ released = (s->npages - s->npreleased) << PageShift;
+ mstats.heap_released += released;
+ sumreleased += released;
+ s->npreleased = s->npages;
+ runtime·SysUnused((void*)(s->start << PageShift), s->npages << PageShift);
+ }
+ }
+ }
+ runtime·unlock(h);
+
+ if(trace) {
+ if(sumreleased > 0)
+ runtime·printf("scvg%d: %p MB released\n", k, sumreleased>>20);
+ runtime·printf("scvg%d: inuse: %D, idle: %D, sys: %D, released: %D, consumed: %D (MB)\n",
+ k, mstats.heap_inuse>>20, mstats.heap_idle>>20, mstats.heap_sys>>20,
+ mstats.heap_released>>20, (mstats.heap_sys - mstats.heap_released)>>20);
+ }
+ }
}
// Initialize a new span with the given start and npages.
@@ -333,6 +412,8 @@
span->ref = 0;
span->sizeclass = 0;
span->state = 0;
+ span->unusedsince = 0;
+ span->npreleased = 0;
}
// Initialize an empty doubly-linked list.
« no previous file with comments | « src/pkg/runtime/mgc0.c ('k') | src/pkg/runtime/proc.c » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b