1
0
mirror of https://github.com/golang/go synced 2024-11-22 03:44:39 -07:00

runtime: faster chan creation on Linux/FreeBSD/Plan9

The change removes chan finalizer (Lock destructor)
if it is not required on the platform.

benchmark                    old ns/op    new ns/op    delta
BenchmarkChanCreation          1132.00       381.00  -66.34%
BenchmarkChanCreation-2        1215.00       243.00  -80.00%
BenchmarkChanCreation-4        1084.00       186.00  -82.84%
BenchmarkChanCreation-8        1415.00       154.00  -89.12%
BenchmarkChanCreation-16       1386.00       144.00  -89.61%
(on 2 x Intel Xeon E5620, 8 HT cores, 2.4 GHz, Linux)

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/4841041
This commit is contained in:
Dmitriy Vyukov 2011-08-04 08:31:03 -04:00 committed by Russ Cox
parent 62d4b8ebd2
commit d770aadee5
9 changed files with 34 additions and 26 deletions

View File

@ -85,7 +85,6 @@ runtime·makechan_c(Type *elem, int64 hint)
{ {
Hchan *c; Hchan *c;
int32 n; int32 n;
byte *by;
if(hint < 0 || (int32)hint != hint || (elem->size > 0 && hint > ((uintptr)-1) / elem->size)) if(hint < 0 || (int32)hint != hint || (elem->size > 0 && hint > ((uintptr)-1) / elem->size))
runtime·panicstring("makechan: size out of range"); runtime·panicstring("makechan: size out of range");
@ -101,9 +100,8 @@ runtime·makechan_c(Type *elem, int64 hint)
n++; n++;
// allocate memory in one call // allocate memory in one call
by = runtime·mal(n + hint*elem->size); c = (Hchan*)runtime·mal(n + hint*elem->size);
if(runtime·destroylock)
c = (Hchan*)by;
runtime·addfinalizer(c, destroychan, 0); runtime·addfinalizer(c, destroychan, 0);
c->elemsize = elem->size; c->elemsize = elem->size;

View File

@ -265,3 +265,25 @@ func BenchmarkChanProdConsWork10(b *testing.B) {
func BenchmarkChanProdConsWork100(b *testing.B) { func BenchmarkChanProdConsWork100(b *testing.B) {
benchmarkChanProdCons(b, 100, 100) benchmarkChanProdCons(b, 100, 100)
} }
func BenchmarkChanCreation(b *testing.B) {
const CallsPerSched = 1000
procs := runtime.GOMAXPROCS(-1)
N := int32(b.N / CallsPerSched)
c := make(chan bool, procs)
for p := 0; p < procs; p++ {
go func() {
for atomic.AddInt32(&N, -1) >= 0 {
for g := 0; g < CallsPerSched; g++ {
myc := make(chan int, 1)
myc <- 0
<-myc
}
}
c <- true
}()
}
for p := 0; p < procs; p++ {
<-c
}
}

View File

@ -82,8 +82,8 @@ runtime·unlock(Lock *l)
} }
} }
void static void
runtime·destroylock(Lock *l) destroylock(Lock *l)
{ {
if(l->sema != 0) { if(l->sema != 0) {
runtime·mach_semdestroy(l->sema); runtime·mach_semdestroy(l->sema);
@ -147,6 +147,7 @@ runtime·osinit(void)
// to let the C pthread libary install its own thread-creation callback. // to let the C pthread libary install its own thread-creation callback.
if(!runtime·iscgo) if(!runtime·iscgo)
runtime·bsdthread_register(); runtime·bsdthread_register();
runtime·destroylock = destroylock;
} }
void void

View File

@ -102,11 +102,6 @@ runtime·unlock(Lock *l)
umtx_unlock(l); umtx_unlock(l);
} }
void
runtime·destroylock(Lock*)
{
}
// Event notifications. // Event notifications.
void void
runtime·noteclear(Note *n) runtime·noteclear(Note *n)

View File

@ -199,11 +199,6 @@ runtime·unlock(Lock *l)
futexunlock(l); futexunlock(l);
} }
void
runtime·destroylock(Lock*)
{
}
// One-time notifications. // One-time notifications.
void void

View File

@ -114,12 +114,6 @@ runtime·unlock(Lock *l)
} }
void
runtime·destroylock(Lock *l)
{
// nothing
}
// User-level semaphore implementation: // User-level semaphore implementation:
// try to do the operations in user space on u, // try to do the operations in user space on u,
// but when it's time to block, fall back on the kernel semaphore k. // but when it's time to block, fall back on the kernel semaphore k.

View File

@ -10,6 +10,7 @@ enum {
}; };
uint32 runtime·panicking; uint32 runtime·panicking;
void (*runtime·destroylock)(Lock*);
/* /*
* We assume that all architectures turn faults and the like * We assume that all architectures turn faults and the like

View File

@ -380,6 +380,7 @@ extern uint32 runtime·panicking;
extern int32 runtime·gcwaiting; // gc is waiting to run extern int32 runtime·gcwaiting; // gc is waiting to run
int8* runtime·goos; int8* runtime·goos;
extern bool runtime·iscgo; extern bool runtime·iscgo;
extern void (*runtime·destroylock)(Lock*);
/* /*
* common functions and data * common functions and data
@ -515,7 +516,6 @@ void runtime·starttheworld(void);
*/ */
void runtime·lock(Lock*); void runtime·lock(Lock*);
void runtime·unlock(Lock*); void runtime·unlock(Lock*);
void runtime·destroylock(Lock*);
/* /*
* sleep and wakeup on one-time events. * sleep and wakeup on one-time events.

View File

@ -40,12 +40,14 @@ extern void *runtime·WaitForSingleObject;
extern void *runtime·WriteFile; extern void *runtime·WriteFile;
static int64 timerfreq; static int64 timerfreq;
static void destroylock(Lock *l);
void void
runtime·osinit(void) runtime·osinit(void)
{ {
runtime·stdcall(runtime·QueryPerformanceFrequency, 1, &timerfreq); runtime·stdcall(runtime·QueryPerformanceFrequency, 1, &timerfreq);
runtime·stdcall(runtime·SetConsoleCtrlHandler, 2, runtime·ctrlhandler, (uintptr)1); runtime·stdcall(runtime·SetConsoleCtrlHandler, 2, runtime·ctrlhandler, (uintptr)1);
runtime·destroylock = destroylock;
} }
void void
@ -154,8 +156,8 @@ runtime·unlock(Lock *l)
eventunlock(l); eventunlock(l);
} }
void static void
runtime·destroylock(Lock *l) destroylock(Lock *l)
{ {
if(l->event != 0) if(l->event != 0)
runtime·stdcall(runtime·CloseHandle, 1, l->event); runtime·stdcall(runtime·CloseHandle, 1, l->event);