mirror of https://github.com/golang/go.git
cmd/gc: apply escape analysis results to closures.
This avoids an allocation when closures are used as "macros", in Walk idioms, or as argument to defer. benchmark old ns/op new ns/op delta BenchmarkSearchWrappers 1171 354 -69.77% BenchmarkCallClosure 3 3 -12.54% BenchmarkCallClosure1 119 7 -93.95% BenchmarkCallClosure2 183 74 -59.18% BenchmarkCallClosure3 187 75 -59.57% BenchmarkCallClosure4 187 76 -58.98% Compared to Go 1: benchmark old ns/op new ns/op delta BenchmarkSearchWrappers 3208 354 -88.97% Fixes #3520. R=daniel.morsing, bradfitz, minux.ma, dave, rsc CC=golang-dev https://golang.org/cl/7397056
This commit is contained in:
parent
4692711d7f
commit
9fe60801ae
|
|
@ -238,14 +238,18 @@ walkclosure(Node *func, NodeList **init)
|
||||||
}
|
}
|
||||||
|
|
||||||
clos = nod(OCOMPLIT, N, nod(OIND, typ, N));
|
clos = nod(OCOMPLIT, N, nod(OIND, typ, N));
|
||||||
|
clos->esc = func->esc;
|
||||||
clos->right->implicit = 1;
|
clos->right->implicit = 1;
|
||||||
clos->list = concat(list1(nod(OCFUNC, func->closure->nname, N)), func->enter);
|
clos->list = concat(list1(nod(OCFUNC, func->closure->nname, N)), func->enter);
|
||||||
|
|
||||||
// Force type conversion from *struct to the func type.
|
// Force type conversion from *struct to the func type.
|
||||||
clos = nod(OCONVNOP, clos, N);
|
clos = nod(OCONVNOP, clos, N);
|
||||||
clos->type = func->type;
|
clos->type = func->type;
|
||||||
|
|
||||||
typecheck(&clos, Erv);
|
typecheck(&clos, Erv);
|
||||||
|
// typecheck will insert a PTRLIT node under CONVNOP,
|
||||||
|
// tag it with escape analysis result.
|
||||||
|
clos->left->esc = func->esc;
|
||||||
walkexpr(&clos, init);
|
walkexpr(&clos, init);
|
||||||
|
|
||||||
return clos;
|
return clos;
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,28 @@ func TestSearchWrappers(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func runSearchWrappers() {
|
||||||
|
SearchInts(data, 11)
|
||||||
|
SearchFloat64s(fdata, 2.1)
|
||||||
|
SearchStrings(sdata, "")
|
||||||
|
IntSlice(data).Search(0)
|
||||||
|
Float64Slice(fdata).Search(2.0)
|
||||||
|
StringSlice(sdata).Search("x")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSearchWrappersDontAlloc(t *testing.T) {
|
||||||
|
allocs := testing.AllocsPerRun(100, runSearchWrappers)
|
||||||
|
if allocs != 0 {
|
||||||
|
t.Errorf("expected no allocs for runSearchWrappers, got %v", allocs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSearchWrappers(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
runSearchWrappers()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Abstract exhaustive test: all sizes up to 100,
|
// Abstract exhaustive test: all sizes up to 100,
|
||||||
// all possible return values. If there are any small
|
// all possible return values. If there are any small
|
||||||
// corner cases, this test exercises them.
|
// corner cases, this test exercises them.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue