Commit 6b2ec065 authored by Dmitriy Vyukov's avatar Dmitriy Vyukov Committed by Russ Cox

runtime: faster select

Make selectsend() accept pointer to the element,
it makes it possible to make Scase fixed-size
and allocate/free Select, all Scase's and all SudoG at once.
As a consequence SudoG freelist die out.

benchmark                       old,ns/op  new,ns/op
BenchmarkSelectUncontended	     1080        558
BenchmarkSelectUncontended-2	      675        264
BenchmarkSelectUncontended-4	      459        205
BenchmarkSelectContended	     1086        560
BenchmarkSelectContended-2	     1775       1672
BenchmarkSelectContended-4	     2668       2149
(on Intel Q6600, 4 cores, 2.4GHz)

benchmark                       old ns/op    new ns/op    delta
BenchmarkSelectUncontended         517.00       326.00  -36.94%
BenchmarkSelectUncontended-2       281.00       166.00  -40.93%
BenchmarkSelectUncontended-4       250.00        83.10  -66.76%
BenchmarkSelectUncontended-8       107.00        47.40  -55.70%
BenchmarkSelectUncontended-16       67.80        41.30  -39.09%
BenchmarkSelectContended           513.00       325.00  -36.65%
BenchmarkSelectContended-2         699.00       628.00  -10.16%
BenchmarkSelectContended-4        1085.00      1092.00   +0.65%
BenchmarkSelectContended-8        3253.00      2477.00  -23.85%
BenchmarkSelectContended-16       5313.00      5116.00   -3.71%
(on Intel E5620, 8 HT cores, 2.4 GHz)

R=rsc, ken
CC=golang-dev
https://golang.org/cl/4811041
parent 17d9093b
......@@ -76,7 +76,7 @@ char *runtimeimport =
"func \"\".selectnbrecv (elem *any, hchan <-chan any) bool\n"
"func \"\".selectnbrecv2 (elem *any, received *bool, hchan <-chan any) bool\n"
"func \"\".newselect (size int) *uint8\n"
"func \"\".selectsend (sel *uint8, hchan chan<- any, elem any) bool\n"
"func \"\".selectsend (sel *uint8, hchan chan<- any, elem *any) bool\n"
"func \"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) bool\n"
"func \"\".selectrecv2 (sel *uint8, hchan <-chan any, elem *any, received *bool) bool\n"
"func \"\".selectdefault (sel *uint8) bool\n"
......
......@@ -1137,6 +1137,7 @@ Sym* restrictlookup(char *name, Pkg *pkg);
Node* safeexpr(Node *n, NodeList **init);
void saveerrors(void);
Node* cheapexpr(Node *n, NodeList **init);
Node* localexpr(Node *n, NodeList **init);
int32 setlineno(Node *n);
void setmaxarg(Type *t);
Type* shallow(Type *t);
......
......@@ -103,7 +103,7 @@ func selectnbrecv(elem *any, hchan <-chan any) bool
func selectnbrecv2(elem *any, received *bool, hchan <-chan any) bool
func newselect(size int) (sel *byte)
func selectsend(sel *byte, hchan chan<- any, elem any) (selected bool)
func selectsend(sel *byte, hchan chan<- any, elem *any) (selected bool)
func selectrecv(sel *byte, hchan <-chan any, elem *any) (selected bool)
func selectrecv2(sel *byte, hchan <-chan any, elem *any, received *bool) (selected bool)
func selectdefault(sel *byte) (selected bool)
......
......@@ -309,7 +309,12 @@ walkselect(Node *sel)
fatal("select %O", n->op);
case OSEND:
// selectsend(sel *byte, hchan *chan any, elem any) (selected bool);
// selectsend(sel *byte, hchan *chan any, elem *any) (selected bool);
n->left = safeexpr(n->left, &r->ninit);
n->right = localexpr(n->right, &r->ninit);
n->right = nod(OADDR, n->right, N);
n->right->etype = 1; // pointer does not escape
typecheck(&n->right, Erv);
r->ntest = mkcall1(chanfn("selectsend", 2, n->left->type), types[TBOOL],
&init, var, n->left, n->right);
break;
......
......@@ -2750,6 +2750,20 @@ safeexpr(Node *n, NodeList **init)
return cheapexpr(n, init);
}
static Node*
copyexpr(Node *n, NodeList **init)
{
Node *a, *l;
l = nod(OXXX, N, N);
tempname(l, n->type);
a = nod(OAS, l, n);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
return l;
}
/*
* return side-effect free and cheap n, appending side effects to init.
* result may not be assignable.
......@@ -2757,21 +2771,26 @@ safeexpr(Node *n, NodeList **init)
Node*
cheapexpr(Node *n, NodeList **init)
{
Node *a, *l;
switch(n->op) {
case ONAME:
case OLITERAL:
return n;
}
l = nod(OXXX, N, N);
tempname(l, n->type);
a = nod(OAS, l, n);
typecheck(&a, Etop);
walkexpr(&a, init);
*init = list(*init, a);
return l;
return copyexpr(n, init);
}
/*
* return n in a local variable if it is not already.
*/
Node*
localexpr(Node *n, NodeList **init)
{
if(n->op == ONAME &&
(n->class == PAUTO || n->class == PPARAM || n->class == PPARAMOUT))
return n;
return copyexpr(n, init);
}
void
......
......@@ -1422,7 +1422,6 @@ synthesizechantypes(DWDie *die)
copychildren(dwh, hchan);
substitutetype(dwh, "recvq", dww);
substitutetype(dwh, "sendq", dww);
substitutetype(dwh, "free", defptrto(dws));
newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT,
getattr(hchan, DW_AT_byte_size)->value, nil);
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment