1
0
mirror of https://github.com/golang/go synced 2024-11-23 07:20:06 -07:00

runtime: faster mcentral alloc.

Reduce individual object handling by anticipating how much of them are servable.

Not a chunked transfer cache, but decent enough to make sure the bottleneck is not here.

Mac OSX, median of 10 runs:

benchmark                 old ns/op    new ns/op    delta
BenchmarkBinaryTree17    5358937333   4892813012   -8.70%
BenchmarkFannkuch11      3257752475   3315436116   +1.77%
BenchmarkGobDecode         23277349     23001114   -1.19%
BenchmarkGobEncode         14367327     14262925   -0.73%
BenchmarkGzip             441045541    440451719   -0.13%
BenchmarkGunzip           139117663    139622494   +0.36%
BenchmarkJSONEncode        45715854     45687802   -0.06%
BenchmarkJSONDecode       103949570    106530032   +2.48%
BenchmarkMandelbrot200      4542462      4548290   +0.13%
BenchmarkParse              7790558      7557540   -2.99%
BenchmarkRevcomp          831436684    832510381   +0.13%
BenchmarkTemplate         133789824    133007337   -0.58%

benchmark                  old MB/s     new MB/s  speedup
BenchmarkGobDecode            32.82        33.33    1.02x
BenchmarkGobEncode            53.42        53.86    1.01x
BenchmarkGzip                 43.70        44.01    1.01x
BenchmarkGunzip              139.09       139.14    1.00x
BenchmarkJSONEncode           42.69        42.56    1.00x
BenchmarkJSONDecode           18.78        17.91    0.95x
BenchmarkParse                 7.37         7.67    1.04x
BenchmarkRevcomp             306.83       305.70    1.00x
BenchmarkTemplate             14.57        14.56    1.00x

R=rsc, dvyukov
CC=golang-dev
https://golang.org/cl/7005055
This commit is contained in:
Sébastien Paolacci 2013-01-18 16:39:22 -05:00 committed by Russ Cox
parent d127ed5378
commit d8626ef128

View File

@ -34,12 +34,13 @@ runtime·MCentral_Init(MCentral *c, int32 sizeclass)
// Allocate up to n objects from the central free list.
// Return the number of objects allocated.
// The objects are linked together by their first words.
// On return, *pstart points at the first object and *pend at the last.
// On return, *pstart points at the first object.
int32
runtime·MCentral_AllocList(MCentral *c, int32 n, MLink **pfirst)
{
MLink *first, *last, *v;
int32 i;
MSpan *s;
MLink *first, *last;
int32 cap, avail, i;
runtime·lock(c);
// Replenish central list if empty.
@ -50,41 +51,34 @@ runtime·MCentral_AllocList(MCentral *c, int32 n, MLink **pfirst)
return 0;
}
}
// Copy from list, up to n.
// First one is guaranteed to work, because we just grew the list.
first = MCentral_Alloc(c);
last = first;
for(i=1; i<n && (v = MCentral_Alloc(c)) != nil; i++) {
last->next = v;
last = v;
}
last->next = nil;
c->nfree -= i;
runtime·unlock(c);
*pfirst = first;
return i;
}
// Helper: allocate one object from the central free list.
static void*
MCentral_Alloc(MCentral *c)
{
MSpan *s;
MLink *v;
if(runtime·MSpanList_IsEmpty(&c->nonempty))
return nil;
s = c->nonempty.next;
s->ref++;
v = s->freelist;
s->freelist = v->next;
if(s->freelist == nil) {
cap = (s->npages << PageShift) / s->elemsize;
avail = cap - s->ref;
if(avail < n)
n = avail;
// First one is guaranteed to work, because we just grew the list.
first = s->freelist;
last = first;
for(i=1; i<n; i++) {
last = last->next;
}
s->freelist = last->next;
last->next = nil;
s->ref += n;
c->nfree -= n;
if(n == avail) {
if(s->freelist != nil || s->ref != cap) {
runtime·throw("invalid freelist");
}
runtime·MSpanList_Remove(s);
runtime·MSpanList_Insert(&c->empty, s);
}
return v;
runtime·unlock(c);
*pfirst = first;
return n;
}
// Free n objects back into the central free list.