]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: do not cache trivial values in DeepEqual.
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Thu, 5 Sep 2013 19:37:07 +0000 (21:37 +0200)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Thu, 5 Sep 2013 19:37:07 +0000 (21:37 +0200)
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

src/pkg/reflect/deepequal.go

index cc6ce056168532618a8bdbffcbbd04bcd5d4501b..e3bf3dcac0c7f49fb73e86322b7d3a5e643184aa 100644 (file)
@@ -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