From: Rémy Oudompheng Date: Thu, 5 Sep 2013 19:37:07 +0000 (+0200) Subject: reflect: do not cache trivial values in DeepEqual. X-Git-Tag: go1.2rc2~345 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=780f5b714dfe9ede57e85cbb804d015981878df4;p=gostls13.git reflect: do not cache trivial values in DeepEqual. DeepEqual caches addresses of compared values each time it visits addressable values. This is more expensive than actually comparing them in the common case of large slices of bytes or integers. Also add a fast path for slices with identical underlying array. R=golang-dev, bradfitz CC=golang-dev https://golang.org/cl/13000044 --- diff --git a/src/pkg/reflect/deepequal.go b/src/pkg/reflect/deepequal.go index cc6ce05616..e3bf3dcac0 100644 --- a/src/pkg/reflect/deepequal.go +++ b/src/pkg/reflect/deepequal.go @@ -28,8 +28,15 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool { } // if depth > 10 { panic("deepValueEqual") } // for debugging + hard := func(k Kind) bool { + switch k { + case Array, Map, Slice, Struct: + return true + } + return false + } - if v1.CanAddr() && v2.CanAddr() { + if v1.CanAddr() && v2.CanAddr() && hard(v1.Kind()) { addr1 := v1.UnsafeAddr() addr2 := v2.UnsafeAddr() if addr1 > addr2 { @@ -71,6 +78,9 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool { if v1.Len() != v2.Len() { return false } + if v1.Pointer() == v2.Pointer() { + return true + } for i := 0; i < v1.Len(); i++ { if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) { return false @@ -98,6 +108,9 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool { if v1.Len() != v2.Len() { return false } + if v1.Pointer() == v2.Pointer() { + return true + } for _, k := range v1.MapKeys() { if !deepValueEqual(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) { return false