mirror of
https://github.com/golang/go
synced 2024-11-18 16:54:43 -07:00
cmd/compile: cache pointer and slice types
Anonymous pointer and slice types are very common and identical anyway, so just reuse them rather than allocating new ones everywhere they appear. Turns out to be a small code/stack size win because SSA relies on gc.Type identity for reusing temporary stack slots: text data bss dec hex filename 6453005 231643 146328 6830976 683b80 go.old 6446660 231643 146328 6824631 6822b7 go.new Saves on memory usage during compile time too, and maybe a small CPU time win, but the benchmarks are pretty noisy: name old time/op new time/op delta Template 342ms ± 8% 339ms ± 9% ~ (p=0.332 n=99+99) Unicode 183ms ± 9% 181ms ±11% ~ (p=0.274 n=95+98) GoTypes 1.05s ± 4% 1.04s ± 3% -1.22% (p=0.000 n=97+95) Compiler 4.49s ± 7% 4.46s ± 6% ~ (p=0.058 n=96+91) name old user-ns/op new user-ns/op delta Template 520M ±17% 522M ±20% ~ (p=0.544 n=98+100) Unicode 331M ±27% 327M ±30% ~ (p=0.615 n=98+98) GoTypes 1.54G ±10% 1.53G ±12% ~ (p=0.173 n=99+100) Compiler 6.33G ±10% 6.33G ±10% ~ (p=0.682 n=98+98) name old alloc/op new alloc/op delta Template 44.5MB ± 0% 44.1MB ± 0% -0.80% (p=0.000 n=97+99) Unicode 37.5MB ± 0% 37.3MB ± 0% -0.44% (p=0.000 n=98+100) GoTypes 126MB ± 0% 124MB ± 0% -1.41% (p=0.000 n=98+99) Compiler 518MB ± 0% 508MB ± 0% -1.90% (p=0.000 n=98+100) name old allocs/op new allocs/op delta Template 441k ± 0% 434k ± 0% -1.76% (p=0.000 n=100+97) Unicode 368k ± 0% 365k ± 0% -0.69% (p=0.000 n=99+99) GoTypes 1.26M ± 0% 1.23M ± 0% -2.27% (p=0.000 n=100+99) Compiler 4.60M ± 0% 4.46M ± 0% -2.96% (p=0.000 n=100+99) Change-Id: I94abce5c57aed0f9c48f567b3ac24c627d4c7c91 Reviewed-on: https://go-review.googlesource.com/30632 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
15937ccb89
commit
78a267e379
@ -26,7 +26,7 @@ func TestSizeof(t *testing.T) {
|
||||
{Name{}, 52, 80},
|
||||
{Node{}, 92, 144},
|
||||
{Sym{}, 60, 112},
|
||||
{Type{}, 52, 80},
|
||||
{Type{}, 60, 96},
|
||||
{MapType{}, 20, 40},
|
||||
{ForwardType{}, 16, 32},
|
||||
{FuncType{}, 28, 48},
|
||||
|
@ -1122,24 +1122,6 @@ func typehash(t *Type) uint32 {
|
||||
return binary.LittleEndian.Uint32(h[:4])
|
||||
}
|
||||
|
||||
var initPtrtoDone bool
|
||||
|
||||
var (
|
||||
ptrToUint8 *Type
|
||||
ptrToAny *Type
|
||||
ptrToString *Type
|
||||
ptrToBool *Type
|
||||
ptrToInt32 *Type
|
||||
)
|
||||
|
||||
func initPtrto() {
|
||||
ptrToUint8 = typPtr(Types[TUINT8])
|
||||
ptrToAny = typPtr(Types[TANY])
|
||||
ptrToString = typPtr(Types[TSTRING])
|
||||
ptrToBool = typPtr(Types[TBOOL])
|
||||
ptrToInt32 = typPtr(Types[TINT32])
|
||||
}
|
||||
|
||||
// ptrto returns the Type *t.
|
||||
// The returned struct must not be modified.
|
||||
func ptrto(t *Type) *Type {
|
||||
@ -1149,23 +1131,6 @@ func ptrto(t *Type) *Type {
|
||||
if t == nil {
|
||||
Fatalf("ptrto: nil ptr")
|
||||
}
|
||||
// Reduce allocations by pre-creating common cases.
|
||||
if !initPtrtoDone {
|
||||
initPtrto()
|
||||
initPtrtoDone = true
|
||||
}
|
||||
switch t {
|
||||
case Types[TUINT8]:
|
||||
return ptrToUint8
|
||||
case Types[TINT32]:
|
||||
return ptrToInt32
|
||||
case Types[TANY]:
|
||||
return ptrToAny
|
||||
case Types[TSTRING]:
|
||||
return ptrToString
|
||||
case Types[TBOOL]:
|
||||
return ptrToBool
|
||||
}
|
||||
return typPtr(t)
|
||||
}
|
||||
|
||||
|
@ -146,6 +146,9 @@ type Type struct {
|
||||
nod *Node // canonical OTYPE node
|
||||
Orig *Type // original type (type literal or predefined type)
|
||||
|
||||
sliceOf *Type
|
||||
ptrTo *Type
|
||||
|
||||
Sym *Sym // symbol containing name, for named types
|
||||
Vargen int32 // unique name for OTYPE/ONAME
|
||||
Lineno int32 // line at which this type was declared, implicitly or explicitly
|
||||
@ -414,10 +417,18 @@ func typArray(elem *Type, bound int64) *Type {
|
||||
return t
|
||||
}
|
||||
|
||||
// typSlice returns a new slice Type.
|
||||
// typSlice returns the slice Type with element type elem.
|
||||
func typSlice(elem *Type) *Type {
|
||||
if t := elem.sliceOf; t != nil {
|
||||
if t.Elem() != elem {
|
||||
Fatalf("elem mismatch")
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
t := typ(TSLICE)
|
||||
t.Extra = SliceType{Elem: elem}
|
||||
elem.sliceOf = t
|
||||
return t
|
||||
}
|
||||
|
||||
@ -446,12 +457,20 @@ func typMap(k, v *Type) *Type {
|
||||
return t
|
||||
}
|
||||
|
||||
// typPtr returns a new pointer type pointing to t.
|
||||
// typPtr returns the pointer type pointing to t.
|
||||
func typPtr(elem *Type) *Type {
|
||||
if t := elem.ptrTo; t != nil {
|
||||
if t.Elem() != elem {
|
||||
Fatalf("elem mismatch")
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
t := typ(Tptr)
|
||||
t.Extra = PtrType{Elem: elem}
|
||||
t.Width = int64(Widthptr)
|
||||
t.Align = uint8(Widthptr)
|
||||
elem.ptrTo = t
|
||||
return t
|
||||
}
|
||||
|
||||
|
@ -3506,6 +3506,9 @@ func copytype(n *Node, t *Type) {
|
||||
embedlineno := n.Type.ForwardType().Embedlineno
|
||||
l := n.Type.ForwardType().Copyto
|
||||
|
||||
ptrTo := n.Type.ptrTo
|
||||
sliceOf := n.Type.sliceOf
|
||||
|
||||
// TODO(mdempsky): Fix Type rekinding.
|
||||
*n.Type = *t
|
||||
|
||||
@ -3519,6 +3522,8 @@ func copytype(n *Node, t *Type) {
|
||||
t.allMethods = Fields{}
|
||||
t.nod = nil
|
||||
t.Deferwidth = false
|
||||
t.ptrTo = ptrTo
|
||||
t.sliceOf = sliceOf
|
||||
|
||||
// Update nodes waiting on this type.
|
||||
for _, n := range l {
|
||||
|
Loading…
Reference in New Issue
Block a user