From 780f5b714dfe9ede57e85cbb804d015981878df4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Oudompheng?= Date: Thu, 5 Sep 2013 21:37:07 +0200 Subject: [PATCH] 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 --- src/pkg/reflect/deepequal.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/pkg/reflect/deepequal.go b/src/pkg/reflect/deepequal.go index cc6ce056168..e3bf3dcac0c 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