mirror of
https://github.com/golang/go
synced 2024-09-25 15:20:13 -06:00
runtime: allocate goroutine ids in batches
Helps reduce contention on sched.goidgen. benchmark old ns/op new ns/op delta BenchmarkCreateGoroutines-16 259 237 -8.49% BenchmarkCreateGoroutinesParallel-16 127 43 -66.06% R=golang-codereviews, dave, bradfitz, khr CC=golang-codereviews, rsc https://golang.org/cl/46970043
This commit is contained in:
parent
8a3c587dc1
commit
98b50b89a8
@ -58,9 +58,16 @@ struct Sched {
|
|||||||
int32 profilehz; // cpu profiling rate
|
int32 profilehz; // cpu profiling rate
|
||||||
};
|
};
|
||||||
|
|
||||||
// The max value of GOMAXPROCS.
|
enum
|
||||||
// There are no fundamental restrictions on the value.
|
{
|
||||||
enum { MaxGomaxprocs = 1<<8 };
|
// The max value of GOMAXPROCS.
|
||||||
|
// There are no fundamental restrictions on the value.
|
||||||
|
MaxGomaxprocs = 1<<8,
|
||||||
|
|
||||||
|
// Number of goroutine ids to grab from runtime·sched.goidgen to local per-P cache at once.
|
||||||
|
// 16 seems to provide enough amortization, but other than that it's mostly arbitrary number.
|
||||||
|
GoidCacheBatch = 16,
|
||||||
|
};
|
||||||
|
|
||||||
Sched runtime·sched;
|
Sched runtime·sched;
|
||||||
int32 runtime·gomaxprocs;
|
int32 runtime·gomaxprocs;
|
||||||
@ -1752,6 +1759,7 @@ runtime·newproc1(FuncVal *fn, byte *argp, int32 narg, int32 nret, void *callerp
|
|||||||
{
|
{
|
||||||
byte *sp;
|
byte *sp;
|
||||||
G *newg;
|
G *newg;
|
||||||
|
P *p;
|
||||||
int32 siz;
|
int32 siz;
|
||||||
|
|
||||||
//runtime·printf("newproc1 %p %p narg=%d nret=%d\n", fn->fn, argp, narg, nret);
|
//runtime·printf("newproc1 %p %p narg=%d nret=%d\n", fn->fn, argp, narg, nret);
|
||||||
@ -1766,7 +1774,8 @@ runtime·newproc1(FuncVal *fn, byte *argp, int32 narg, int32 nret, void *callerp
|
|||||||
if(siz > StackMin - 1024)
|
if(siz > StackMin - 1024)
|
||||||
runtime·throw("runtime.newproc: function arguments too large for new goroutine");
|
runtime·throw("runtime.newproc: function arguments too large for new goroutine");
|
||||||
|
|
||||||
if((newg = gfget(m->p)) != nil) {
|
p = m->p;
|
||||||
|
if((newg = gfget(p)) != nil) {
|
||||||
if(newg->stackguard - StackGuard != newg->stack0)
|
if(newg->stackguard - StackGuard != newg->stack0)
|
||||||
runtime·throw("invalid stack in newg");
|
runtime·throw("invalid stack in newg");
|
||||||
} else {
|
} else {
|
||||||
@ -1790,11 +1799,15 @@ runtime·newproc1(FuncVal *fn, byte *argp, int32 narg, int32 nret, void *callerp
|
|||||||
runtime·gostartcallfn(&newg->sched, fn);
|
runtime·gostartcallfn(&newg->sched, fn);
|
||||||
newg->gopc = (uintptr)callerpc;
|
newg->gopc = (uintptr)callerpc;
|
||||||
newg->status = Grunnable;
|
newg->status = Grunnable;
|
||||||
newg->goid = runtime·xadd64(&runtime·sched.goidgen, 1);
|
if(p->goidcache == p->goidcacheend) {
|
||||||
|
p->goidcache = runtime·xadd64(&runtime·sched.goidgen, GoidCacheBatch);
|
||||||
|
p->goidcacheend = p->goidcache + GoidCacheBatch;
|
||||||
|
}
|
||||||
|
newg->goid = p->goidcache++;
|
||||||
newg->panicwrap = 0;
|
newg->panicwrap = 0;
|
||||||
if(raceenabled)
|
if(raceenabled)
|
||||||
newg->racectx = runtime·racegostart((void*)callerpc);
|
newg->racectx = runtime·racegostart((void*)callerpc);
|
||||||
runqput(m->p, newg);
|
runqput(p, newg);
|
||||||
|
|
||||||
if(runtime·atomicload(&runtime·sched.npidle) != 0 && runtime·atomicload(&runtime·sched.nmspinning) == 0 && fn->fn != runtime·main) // TODO: fast atomic
|
if(runtime·atomicload(&runtime·sched.npidle) != 0 && runtime·atomicload(&runtime·sched.nmspinning) == 0 && fn->fn != runtime·main) // TODO: fast atomic
|
||||||
wakep();
|
wakep();
|
||||||
|
@ -385,6 +385,10 @@ struct P
|
|||||||
MCache* mcache;
|
MCache* mcache;
|
||||||
Defer* deferpool[5]; // pool of available Defer structs of different sizes (see panic.c)
|
Defer* deferpool[5]; // pool of available Defer structs of different sizes (see panic.c)
|
||||||
|
|
||||||
|
// Cache of goroutine ids, amortizes accesses to runtime·sched.goidgen.
|
||||||
|
uint64 goidcache;
|
||||||
|
uint64 goidcacheend;
|
||||||
|
|
||||||
// Queue of runnable goroutines.
|
// Queue of runnable goroutines.
|
||||||
uint32 runqhead;
|
uint32 runqhead;
|
||||||
uint32 runqtail;
|
uint32 runqtail;
|
||||||
|
Loading…
Reference in New Issue
Block a user