]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: cache pointer and slice types
authorMatthew Dempsky <mdempsky@google.com>
Thu, 6 Oct 2016 22:50:47 +0000 (15:50 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Fri, 7 Oct 2016 00:04:40 +0000 (00:04 +0000)
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>
src/cmd/compile/internal/gc/sizeof_test.go
src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/gc/type.go
src/cmd/compile/internal/gc/typecheck.go

index 1a0e53057ccbdd6b8db84034ecb6d51918079fed..185b19135aa2a152c65d64848168149f54db9e24 100644 (file)
@@ -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},
index 39951ac05a44d31e222c6a43f001f67f835d0c40..449a5a62cbb77ef78886942e3b88b629906dd8a1 100644 (file)
@@ -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)
 }
 
index 4db2b255c842e9c9bc165c4ff17624bc6eb609a8..2dd1184fffd3a4df4b1e9f98f4989f7111fba4cb 100644 (file)
@@ -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
 }
 
index f2c6f5a3e98fdb690ff5cb5faac3580f86b09f99..01ca8922d442bb017812ecdec5e65bc6c63d242f 100644 (file)
@@ -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 {