Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reflect: export DeepValueEqual #32321

Closed
masterada opened this issue May 30, 2019 · 2 comments
Closed

reflect: export DeepValueEqual #32321

masterada opened this issue May 30, 2019 · 2 comments
Labels
FeatureRequest Issues asking for a new feature that does not need a proposal. FrozenDueToAge Performance WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.

Comments

@masterada
Copy link

I have two values with type reflect.Value. I would like to call reflect.DeepEquals on them. Currently I'm doing it this way:

reflect.DeepEqual(v1.Interface(), v2.Interface())

This seems like a waste of cpu time, as DeepEqual will just wrap them again with reflect.Value.

Would it be possible to add a method like this?

func DeepValueEqual(v1, v2 Value) bool {
	if v1.Type() != v2.Type() {
		return false
	}
	return deepValueEqual(v1, v2, make(map[visit]bool), 0)
}
@mvdan
Copy link
Member

mvdan commented May 30, 2019

If this proposal is based on performance, have you measured the impact with a benchmark? You could use simple values, so that the comparison itself is little work.

@bcmills bcmills added FeatureRequest Issues asking for a new feature that does not need a proposal. Performance WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. labels May 30, 2019
@masterada
Copy link
Author

very suprising results, never imagined converting string to interface would take up half the time:

code:


var e bool

func benchmarkDeepEqual(b *testing.B, s1 string, s2 string) {
	var i1 interface{} = s1
	var i2 interface{} = s2

	v1 := reflect.ValueOf(s1)
	v2 := reflect.ValueOf(s2)

	b.Run("DeepEqual_string", func(b *testing.B) {
		for n := 0; n < b.N; n++ {
			e = reflect.DeepEqual(s1, s2)
		}
	})

	b.Run("DeepEqual_interface", func(b *testing.B) {
		for n := 0; n < b.N; n++ {
			e = reflect.DeepEqual(i1, i2)
		}
	})

	b.Run("DeepEqual_Value", func(b *testing.B) {
		for n := 0; n < b.N; n++ {
			e = reflect.DeepEqual(v1.Interface(), v2.Interface())
		}
	})

	b.Run("DeepValueEqual", func(b *testing.B) {
		for n := 0; n < b.N; n++ {
			e = reflect.DeepValueEqual(v1, v2)
		}
	})
}

func BenchmarkDeepEqual_eq(b *testing.B)  { benchmarkDeepEqual(b, "test", "test") }
func BenchmarkDeepEqual_neq(b *testing.B) { benchmarkDeepEqual(b, "test", "test2") }

results:

BenchmarkDeepEqual_eq/DeepEqual_string-4         	10000000	       144 ns/op
BenchmarkDeepEqual_eq/DeepEqual_interface-4      	20000000	        78.1 ns/op
BenchmarkDeepEqual_eq/DeepEqual_Value-4          	20000000	        91.3 ns/op
BenchmarkDeepEqual_eq/DeepValueEqual-4           	20000000	        73.0 ns/op
BenchmarkDeepEqual_neq/DeepEqual_string-4        	10000000	       142 ns/op
BenchmarkDeepEqual_neq/DeepEqual_interface-4     	20000000	        72.1 ns/op
BenchmarkDeepEqual_neq/DeepEqual_Value-4         	20000000	        88.4 ns/op
BenchmarkDeepEqual_neq/DeepValueEqual-4          	20000000	        67.7 ns/op

@golang golang locked and limited conversation to collaborators May 29, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FeatureRequest Issues asking for a new feature that does not need a proposal. FrozenDueToAge Performance WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

4 participants