Commit 780f5b71 authored by Rémy Oudompheng's avatar Rémy Oudompheng

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
parent f2380a81
...@@ -28,8 +28,15 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool { ...@@ -28,8 +28,15 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
} }
// if depth > 10 { panic("deepValueEqual") } // for debugging // 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() addr1 := v1.UnsafeAddr()
addr2 := v2.UnsafeAddr() addr2 := v2.UnsafeAddr()
if addr1 > addr2 { if addr1 > addr2 {
...@@ -71,6 +78,9 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool { ...@@ -71,6 +78,9 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
if v1.Len() != v2.Len() { if v1.Len() != v2.Len() {
return false return false
} }
if v1.Pointer() == v2.Pointer() {
return true
}
for i := 0; i < v1.Len(); i++ { for i := 0; i < v1.Len(); i++ {
if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) { if !deepValueEqual(v1.Index(i), v2.Index(i), visited, depth+1) {
return false return false
...@@ -98,6 +108,9 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool { ...@@ -98,6 +108,9 @@ func deepValueEqual(v1, v2 Value, visited map[visit]bool, depth int) bool {
if v1.Len() != v2.Len() { if v1.Len() != v2.Len() {
return false return false
} }
if v1.Pointer() == v2.Pointer() {
return true
}
for _, k := range v1.MapKeys() { for _, k := range v1.MapKeys() {
if !deepValueEqual(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) { if !deepValueEqual(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) {
return false return false
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment