runtime.newobject never returns the same thing twice,
so the resulting value will never be a common subexpression.
This helps when compiling large static data structures
that include pointers, such as maps and slices.
No clear performance impact on other code. (See below.)
For the code in issue #15112:
Before:
real 1m14.238s
user 1m18.985s
sys 0m0.787s
After:
real 0m47.172s
user 0m52.248s
sys 0m0.767s
For the code in issue #15235, size 10k:
Before:
real 0m44.916s
user 0m46.577s
sys 0m0.304s
After:
real 0m7.703s
user 0m9.041s
sys 0m0.316s
Still more work to be done, particularly for #15112.
Updates #15112
Updates #15235
name old time/op new time/op delta
Template 330ms ±11% 333ms ±13% ~ (p=0.749 n=20+19)
Unicode 148ms ± 6% 152ms ± 8% ~ (p=0.072 n=18+20)
GoTypes 1.01s ± 7% 1.01s ± 3% ~ (p=0.583 n=20+20)
Compiler 5.04s ± 2% 5.06s ± 2% ~ (p=0.314 n=20+20)
name old user-ns/op new user-ns/op delta
Template 444user-ms ±11% 445user-ms ±10% ~ (p=0.738 n=20+20)
Unicode 215user-ms ± 5% 218user-ms ± 5% ~ (p=0.239 n=18+18)
GoTypes 1.45user-s ± 3% 1.45user-s ± 4% ~ (p=0.620 n=20+20)
Compiler 7.23user-s ± 2% 7.22user-s ± 2% ~ (p=0.901 n=20+19)
name old alloc/op new alloc/op delta
Template 55.0MB ± 0% 55.0MB ± 0% ~ (p=0.547 n=20+20)
Unicode 37.6MB ± 0% 37.6MB ± 0% ~ (p=0.301 n=20+20)
GoTypes 177MB ± 0% 177MB ± 0% ~ (p=0.065 n=20+19)
Compiler 798MB ± 0% 797MB ± 0% -0.05% (p=0.000 n=19+20)
name old allocs/op new allocs/op delta
Template 492k ± 0% 493k ± 0% +0.03% (p=0.030 n=20+20)
Unicode 377k ± 0% 377k ± 0% ~ (p=0.423 n=20+19)
GoTypes 1.40M ± 0% 1.40M ± 0% ~ (p=0.102 n=20+20)
Compiler 5.53M ± 0% 5.53M ± 0% ~ (p=0.094 n=17+18)
name old text-bytes new text-bytes delta
HelloSize 561k ± 0% 561k ± 0% ~ (all samples are equal)
CmdGoSize 6.13M ± 0% 6.13M ± 0% ~ (all samples are equal)
name old data-bytes new data-bytes delta
HelloSize 128k ± 0% 128k ± 0% ~ (all samples are equal)
CmdGoSize 306k ± 0% 306k ± 0% ~ (all samples are equal)
name old exe-bytes new exe-bytes delta
HelloSize 905k ± 0% 905k ± 0% ~ (all samples are equal)
CmdGoSize 9.64M ± 0% 9.64M ± 0% ~ (all samples are equal)
Change-Id: Id774e2901d7701a3ec7a1c1d1cf1d9327a4107fc
Reviewed-on: https://go-review.googlesource.com/21937
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
return s.Def
}
+func (s *Sym) IsRuntimeCall(name string) bool {
+ return s.Pkg == Runtimepkg && s.Name == name
+}
+
// typehash computes a hash value for type t to use in type switch
// statements.
func typehash(t *Type) uint32 {
String() string
}
+// GCSym is an interface that *gc.Sym implements.
+// Using *gc.Sym directly would lead to import cycles.
+type GCSym interface {
+ IsRuntimeCall(name string) bool
+}
+
// NewConfig returns a new configuration object for the given architecture.
func NewConfig(arch string, fe Frontend, ctxt *obj.Link, optimize bool) *Config {
c := &Config{arch: arch, fe: fe}
return lt2Cmp(v.Block.ID < w.Block.ID)
}
+ switch v.Op {
+ case OpStaticCall, OpAMD64CALLstatic, OpARMCALLstatic:
+ sym := v.Aux.(GCSym)
+ if sym.IsRuntimeCall("newobject") {
+ return lt2Cmp(v.ID < w.ID)
+ }
+ }
+
if tc := v.Type.Compare(w.Type); tc != CMPeq {
return tc
}