1
0
mirror of https://github.com/golang/go synced 2024-11-19 15:14:45 -07:00

runtime: eliminate false sharing on random number generators

Use machine-local random number generator instead of
racy global ones.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/4674049
This commit is contained in:
Dmitriy Vyukov 2011-07-12 01:23:58 -04:00 committed by Russ Cox
parent f9f21aa1fb
commit 909f31872a
5 changed files with 20 additions and 29 deletions

View File

@ -1221,17 +1221,6 @@ freesg(Hchan *c, SudoG *sg)
} }
} }
static uint32
fastrand1(void)
{
static uint32 x = 0x49f6428aUL;
x += x;
if(x & 0x80000000L)
x ^= 0x88888eefUL;
return x;
}
static uint32 static uint32
fastrandn(uint32 n) fastrandn(uint32 n)
{ {
@ -1240,12 +1229,12 @@ fastrandn(uint32 n)
if(n <= 1) if(n <= 1)
return 0; return 0;
r = fastrand1(); r = runtime·fastrand1();
if(r < (1ULL<<31)-n) // avoid computing max in common case if(r < (1ULL<<31)-n) // avoid computing max in common case
return r%n; return r%n;
max = (1ULL<<31)/n * n; max = (1ULL<<31)/n * n;
while(r >= max) while(r >= max)
r = fastrand1(); r = runtime·fastrand1();
return r%n; return r%n;
} }

View File

@ -18,21 +18,6 @@ extern MStats mstats; // defined in extern.go
extern volatile int32 runtime·MemProfileRate; extern volatile int32 runtime·MemProfileRate;
// Same algorithm from chan.c, but a different
// instance of the static uint32 x.
// Not protected by a lock - let the threads use
// the same random number if they like.
static uint32
fastrand1(void)
{
static uint32 x = 0x49f6428aUL;
x += x;
if(x & 0x80000000L)
x ^= 0x88888eefUL;
return x;
}
// Allocate an object of at least size bytes. // Allocate an object of at least size bytes.
// Small objects are allocated from the per-thread cache's free lists. // Small objects are allocated from the per-thread cache's free lists.
// Large objects (> 32 kB) are allocated straight from the heap. // Large objects (> 32 kB) are allocated straight from the heap.
@ -97,7 +82,7 @@ runtime·mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
// pick next profile time // pick next profile time
if(rate > 0x3fffffff) // make 2*rate not overflow if(rate > 0x3fffffff) // make 2*rate not overflow
rate = 0x3fffffff; rate = 0x3fffffff;
m->mcache->next_sample = fastrand1() % (2*rate); m->mcache->next_sample = runtime·fastrand1() % (2*rate);
profile: profile:
runtime·setblockspecial(v); runtime·setblockspecial(v);
runtime·MProf_Malloc(v, size); runtime·MProf_Malloc(v, size);

View File

@ -117,6 +117,7 @@ runtime·schedinit(void)
runtime·allm = m; runtime·allm = m;
m->nomemprof++; m->nomemprof++;
m->fastrand = 0x49f6428aUL + m->id;
runtime·mallocinit(); runtime·mallocinit();
runtime·goargs(); runtime·goargs();
@ -495,6 +496,7 @@ matchmg(void)
m->alllink = runtime·allm; m->alllink = runtime·allm;
runtime·allm = m; runtime·allm = m;
m->id = runtime·sched.mcount++; m->id = runtime·sched.mcount++;
m->fastrand = 0x49f6428aUL + m->id;
if(runtime·iscgo) { if(runtime·iscgo) {
CgoThreadStart ts; CgoThreadStart ts;

View File

@ -588,3 +588,16 @@ runtime·FuncForPC(uintptr pc, void *retf)
retf = runtime·findfunc(pc); retf = runtime·findfunc(pc);
FLUSH(&retf); FLUSH(&retf);
} }
uint32
runtime·fastrand1(void)
{
uint32 x;
x = m->fastrand;
x += x;
if(x & 0x80000000L)
x ^= 0x88888eefUL;
m->fastrand = x;
return x;
}

View File

@ -229,6 +229,7 @@ struct M
int32 waitnextg; int32 waitnextg;
int32 dying; int32 dying;
int32 profilehz; int32 profilehz;
uint32 fastrand;
Note havenextg; Note havenextg;
G* nextg; G* nextg;
M* alllink; // on allm M* alllink; // on allm
@ -454,6 +455,7 @@ void runtime·runpanic(Panic*);
void* runtime·getcallersp(void*); void* runtime·getcallersp(void*);
int32 runtime·mcount(void); int32 runtime·mcount(void);
void runtime·mcall(void(*)(G*)); void runtime·mcall(void(*)(G*));
uint32 runtime·fastrand1(void);
void runtime·exit(int32); void runtime·exit(int32);
void runtime·breakpoint(void); void runtime·breakpoint(void);