Commit e71d1477 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

runtime: fix mem profile when both large and small objects are allocated at the same stack

Currently small and large (size>rate) objects are merged into a single entry.
But rate adjusting is required only for small objects.
As a result pprof either incorrectly adjusts large objects
or does not adjust small objects.
With this change objects of different sizes are stored in different buckets.

LGTM=rsc
R=golang-codereviews, gobot, rsc
CC=golang-codereviews
https://golang.org/cl/59220049
parent f0023cf1
...@@ -67,7 +67,8 @@ struct Bucket ...@@ -67,7 +67,8 @@ struct Bucket
int64 cycles; int64 cycles;
}; };
}; };
uintptr hash; uintptr hash; // hash of size + stk
uintptr size;
uintptr nstk; uintptr nstk;
uintptr stk[1]; uintptr stk[1];
}; };
...@@ -81,7 +82,7 @@ static uintptr bucketmem; ...@@ -81,7 +82,7 @@ static uintptr bucketmem;
// Return the bucket for stk[0:nstk], allocating new bucket if needed. // Return the bucket for stk[0:nstk], allocating new bucket if needed.
static Bucket* static Bucket*
stkbucket(int32 typ, uintptr *stk, int32 nstk, bool alloc) stkbucket(int32 typ, uintptr size, uintptr *stk, int32 nstk, bool alloc)
{ {
int32 i; int32 i;
uintptr h; uintptr h;
...@@ -100,12 +101,17 @@ stkbucket(int32 typ, uintptr *stk, int32 nstk, bool alloc) ...@@ -100,12 +101,17 @@ stkbucket(int32 typ, uintptr *stk, int32 nstk, bool alloc)
h += h<<10; h += h<<10;
h ^= h>>6; h ^= h>>6;
} }
// hash in size
h += size;
h += h<<10;
h ^= h>>6;
// finalize
h += h<<3; h += h<<3;
h ^= h>>11; h ^= h>>11;
i = h%BuckHashSize; i = h%BuckHashSize;
for(b = buckhash[i]; b; b=b->next) for(b = buckhash[i]; b; b=b->next)
if(b->typ == typ && b->hash == h && b->nstk == nstk && if(b->typ == typ && b->hash == h && b->size == size && b->nstk == nstk &&
runtime·mcmp((byte*)b->stk, (byte*)stk, nstk*sizeof stk[0]) == 0) runtime·mcmp((byte*)b->stk, (byte*)stk, nstk*sizeof stk[0]) == 0)
return b; return b;
...@@ -117,6 +123,7 @@ stkbucket(int32 typ, uintptr *stk, int32 nstk, bool alloc) ...@@ -117,6 +123,7 @@ stkbucket(int32 typ, uintptr *stk, int32 nstk, bool alloc)
runtime·memmove(b->stk, stk, nstk*sizeof stk[0]); runtime·memmove(b->stk, stk, nstk*sizeof stk[0]);
b->typ = typ; b->typ = typ;
b->hash = h; b->hash = h;
b->size = size;
b->nstk = nstk; b->nstk = nstk;
b->next = buckhash[i]; b->next = buckhash[i];
buckhash[i] = b; buckhash[i] = b;
...@@ -231,7 +238,7 @@ runtime·MProf_Malloc(void *p, uintptr size, uintptr typ) ...@@ -231,7 +238,7 @@ runtime·MProf_Malloc(void *p, uintptr size, uintptr typ)
runtime·printf(">)\n"); runtime·printf(">)\n");
printstackframes(stk, nstk); printstackframes(stk, nstk);
} }
b = stkbucket(MProf, stk, nstk, true); b = stkbucket(MProf, size, stk, nstk, true);
b->recent_allocs++; b->recent_allocs++;
b->recent_alloc_bytes += size; b->recent_alloc_bytes += size;
runtime·unlock(&proflock); runtime·unlock(&proflock);
...@@ -296,7 +303,7 @@ runtime·blockevent(int64 cycles, int32 skip) ...@@ -296,7 +303,7 @@ runtime·blockevent(int64 cycles, int32 skip)
nstk = runtime·callers(skip, stk, nelem(stk)); nstk = runtime·callers(skip, stk, nelem(stk));
runtime·lock(&proflock); runtime·lock(&proflock);
b = stkbucket(BProf, stk, nstk, true); b = stkbucket(BProf, 0, stk, nstk, true);
b->count++; b->count++;
b->cycles += cycles; b->cycles += cycles;
runtime·unlock(&proflock); runtime·unlock(&proflock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment