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:
parent
62d4b8ebd2
commit
d770aadee5
@ -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;
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -199,11 +199,6 @@ runtime·unlock(Lock *l)
|
|||||||
futexunlock(l);
|
futexunlock(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
runtime·destroylock(Lock*)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// One-time notifications.
|
// One-time notifications.
|
||||||
void
|
void
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user