1
0
mirror of https://github.com/golang/go synced 2024-10-04 04:41:23 -06:00
go/src/pkg/runtime/mcache.c
Dmitriy Vyukov c14b2689f0 runtime: faster finalizers
Linux/amd64, 2 x Intel Xeon E5620, 8 HT cores, 2.40GHz
benchmark                    old ns/op    new ns/op    delta
BenchmarkFinalizer              420.00       261.00  -37.86%
BenchmarkFinalizer-2            985.00       201.00  -79.59%
BenchmarkFinalizer-4           1077.00       244.00  -77.34%
BenchmarkFinalizer-8           1155.00       180.00  -84.42%
BenchmarkFinalizer-16          1182.00       184.00  -84.43%

BenchmarkFinalizerRun          2128.00      1378.00  -35.24%
BenchmarkFinalizerRun-2        1655.00      1418.00  -14.32%
BenchmarkFinalizerRun-4        1634.00      1522.00   -6.85%
BenchmarkFinalizerRun-8        2213.00      1581.00  -28.56%
BenchmarkFinalizerRun-16       2424.00      1599.00  -34.03%

Darwin/amd64, Intel L9600, 2 cores, 2.13GHz
benchmark                    old ns/op    new ns/op    delta
BenchmarkChanCreation          1451.00       926.00  -36.18%
BenchmarkChanCreation-2        3124.00      1412.00  -54.80%
BenchmarkChanCreation-4        6121.00      2628.00  -57.07%

BenchmarkFinalizer              684.00       420.00  -38.60%
BenchmarkFinalizer-2          11195.00       398.00  -96.44%
BenchmarkFinalizer-4          15862.00       654.00  -95.88%

BenchmarkFinalizerRun          2025.00      1397.00  -31.01%
BenchmarkFinalizerRun-2        3920.00      1447.00  -63.09%
BenchmarkFinalizerRun-4        9471.00      1545.00  -83.69%

R=golang-dev, cw, rsc
CC=golang-dev
https://golang.org/cl/4963057
2011-10-06 18:42:51 +03:00

135 lines
2.9 KiB
C

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Per-thread (in Go, per-M) malloc cache for small objects.
//
// See malloc.h for an overview.
#include "runtime.h"
#include "arch.h"
#include "malloc.h"
void*
runtime·MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroed)
{
MCacheList *l;
MLink *first, *v;
int32 n;
// Allocate from list.
l = &c->list[sizeclass];
if(l->list == nil) {
// Replenish using central lists.
n = runtime·MCentral_AllocList(&runtime·mheap.central[sizeclass],
runtime·class_to_transfercount[sizeclass], &first);
if(n == 0)
runtime·throw("out of memory");
l->list = first;
l->nlist = n;
c->size += n*size;
}
v = l->list;
l->list = v->next;
l->nlist--;
if(l->nlist < l->nlistmin)
l->nlistmin = l->nlist;
c->size -= size;
// v is zeroed except for the link pointer
// that we used above; zero that.
v->next = nil;
if(zeroed) {
// block is zeroed iff second word is zero ...
if(size > sizeof(uintptr) && ((uintptr*)v)[1] != 0)
runtime·memclr((byte*)v, size);
else {
// ... except for the link pointer
// that we used above; zero that.
v->next = nil;
}
}
c->local_cachealloc += size;
c->local_objects++;
return v;
}
// Take n elements off l and return them to the central free list.
static void
ReleaseN(MCache *c, MCacheList *l, int32 n, int32 sizeclass)
{
MLink *first, **lp;
int32 i;
// Cut off first n elements.
first = l->list;
lp = &l->list;
for(i=0; i<n; i++)
lp = &(*lp)->next;
l->list = *lp;
*lp = nil;
l->nlist -= n;
if(l->nlist < l->nlistmin)
l->nlistmin = l->nlist;
c->size -= n*runtime·class_to_size[sizeclass];
// Return them to central free list.
runtime·MCentral_FreeList(&runtime·mheap.central[sizeclass], n, first);
}
void
runtime·MCache_Free(MCache *c, void *v, int32 sizeclass, uintptr size)
{
int32 i, n;
MCacheList *l;
MLink *p;
// Put back on list.
l = &c->list[sizeclass];
p = v;
p->next = l->list;
l->list = p;
l->nlist++;
c->size += size;
c->local_cachealloc -= size;
c->local_objects--;
if(l->nlist >= MaxMCacheListLen) {
// Release a chunk back.
ReleaseN(c, l, runtime·class_to_transfercount[sizeclass], sizeclass);
}
if(c->size >= MaxMCacheSize) {
// Scavenge.
for(i=0; i<NumSizeClasses; i++) {
l = &c->list[i];
n = l->nlistmin;
// n is the minimum number of elements we've seen on
// the list since the last scavenge. If n > 0, it means that
// we could have gotten by with n fewer elements
// without needing to consult the central free list.
// Move toward that situation by releasing n/2 of them.
if(n > 0) {
if(n > 1)
n /= 2;
ReleaseN(c, l, n, i);
}
l->nlistmin = l->nlist;
}
}
}
void
runtime·MCache_ReleaseAll(MCache *c)
{
int32 i;
MCacheList *l;
for(i=0; i<NumSizeClasses; i++) {
l = &c->list[i];
ReleaseN(c, l, l->nlist, i);
l->nlistmin = 0;
}
}