aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime
diff options
context:
space:
mode:
authorDmitriy Vyukov <dvyukov@google.com>2014-02-12 22:36:45 +0400
committerDmitriy Vyukov <dvyukov@google.com>2014-02-12 22:36:45 +0400
commitbf0d71af2907401a83f846d2f6baff38029aa4cd (patch)
treef79e2e3c6f57a7da734233d7d9139a0384979f83 /src/pkg/runtime
parent5e72fae9b2c4fddc67a5d8ea0aecf3f73234d83e (diff)
downloadgo-bf0d71af2907401a83f846d2f6baff38029aa4cd.tar.xz
runtime: more precise mprof sampling
Better sampling of objects that are close in size to sampling rate. See the comment for details. LGTM=rsc R=golang-codereviews, rsc CC=golang-codereviews https://golang.org/cl/43830043
Diffstat (limited to 'src/pkg/runtime')
-rw-r--r--src/pkg/runtime/malloc.goc47
1 files changed, 34 insertions, 13 deletions
diff --git a/src/pkg/runtime/malloc.goc b/src/pkg/runtime/malloc.goc
index babfb9e176..db2f9537a9 100644
--- a/src/pkg/runtime/malloc.goc
+++ b/src/pkg/runtime/malloc.goc
@@ -28,6 +28,7 @@ extern MStats mstats; // defined in zruntime_def_$GOOS_$GOARCH.go
extern volatile intgo runtime·MemProfileRate;
static void* largealloc(uint32, uintptr*);
+static void profilealloc(void *v, uintptr size, uintptr typ);
// Allocate an object of at least size bytes.
// Small objects are allocated from the per-thread cache's free lists.
@@ -191,29 +192,23 @@ runtime·mallocgc(uintptr size, uintptr typ, uint32 flag)
runtime·settype_flush(m);
if(raceenabled)
runtime·racemalloc(v, size);
- m->locks--;
- if(m->locks == 0 && g->preempt) // restore the preemption request in case we've cleared it in newstack
- g->stackguard0 = StackPreempt;
if(runtime·debug.allocfreetrace)
goto profile;
if(!(flag & FlagNoProfiling) && (rate = runtime·MemProfileRate) > 0) {
- if(size >= rate)
- goto profile;
- if(m->mcache->next_sample > size)
- m->mcache->next_sample -= size;
+ if(size < rate && size < c->next_sample)
+ c->next_sample -= size;
else {
- // pick next profile time
- // If you change this, also change allocmcache.
- if(rate > 0x3fffffff) // make 2*rate not overflow
- rate = 0x3fffffff;
- m->mcache->next_sample = runtime·fastrand1() % (2*rate);
profile:
- runtime·MProf_Malloc(v, size, typ);
+ profilealloc(v, size, typ);
}
}
+ m->locks--;
+ if(m->locks == 0 && g->preempt) // restore the preemption request in case we've cleared it in newstack
+ g->stackguard0 = StackPreempt;
+
if(!(flag & FlagNoInvokeGC) && mstats.heap_alloc >= mstats.next_gc)
runtime·gc(0);
@@ -245,6 +240,32 @@ largealloc(uint32 flag, uintptr *sizep)
return v;
}
+static void
+profilealloc(void *v, uintptr size, uintptr typ)
+{
+ uintptr rate;
+ int32 next;
+ MCache *c;
+
+ c = m->mcache;
+ rate = runtime·MemProfileRate;
+ if(size < rate) {
+ // pick next profile time
+ // If you change this, also change allocmcache.
+ if(rate > 0x3fffffff) // make 2*rate not overflow
+ rate = 0x3fffffff;
+ next = runtime·fastrand1() % (2*rate);
+ // Subtract the "remainder" of the current allocation.
+ // Otherwise objects that are close in size to sampling rate
+ // will be under-sampled, because we consistently discard this remainder.
+ next -= (size - c->next_sample);
+ if(next < 0)
+ next = 0;
+ c->next_sample = next;
+ }
+ runtime·MProf_Malloc(v, size, typ);
+}
+
void*
runtime·malloc(uintptr size)
{