Skip to content

Commit 25f0e42

Browse files
Antoine Pelisseapelisse
Antoine Pelisse
authored andcommitted
Implement equality for Values
Equality doesn't require the same amount of sophistication than ordering comparison. Implement an Equal function that does just that but does it much faster. Benchmark results show up to 96% improvement: ``` benchmark old ns/op new ns/op delta BenchmarkDeducedSimple-12 110083 103256 -6.20% BenchmarkDeducedNested-12 374366 374160 -0.06% BenchmarkDeducedNestedAcrossVersion-12 392864 405525 +3.22% BenchmarkLeafConflictAcrossVersion-12 89112 89070 -0.05% BenchmarkMultipleApplierRecursiveRealConversion-12 1564330 1574620 +0.66% BenchmarkOperations/Pod/Create-12 103693 103970 +0.27% BenchmarkOperations/Pod/Apply-12 291760 291317 -0.15% BenchmarkOperations/Pod/Update-12 193419 190470 -1.52% BenchmarkOperations/Pod/UpdateVersion-12 261692 251966 -3.72% BenchmarkOperations/Node/Create-12 152047 155710 +2.41% BenchmarkOperations/Node/Apply-12 499187 473901 -5.07% BenchmarkOperations/Node/Update-12 299271 279142 -6.73% BenchmarkOperations/Node/UpdateVersion-12 438723 403125 -8.11% BenchmarkOperations/Endpoints/Create-12 12246 11940 -2.50% BenchmarkOperations/Endpoints/Apply-12 915806 924080 +0.90% BenchmarkOperations/Endpoints/Update-12 7155675 285092 -96.02% BenchmarkOperations/Endpoints/UpdateVersion-12 14278150 544040 -96.19% BenchmarkOperations/CustomResourceDefinition/Create-12 1312734 1288472 -1.85% BenchmarkOperations/CustomResourceDefinition/Apply-12 3346591 3376864 +0.90% BenchmarkOperations/CustomResourceDefinition/Update-12 10681243 1758764 -83.53% BenchmarkOperations/CustomResourceDefinition/UpdateVersion-12 19069925 2202330 -88.45% ```
1 parent 1ad9a28 commit 25f0e42

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

value/less_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,9 @@ func TestValueLess(t *testing.T) {
296296
t.Run(table[i].name, func(t *testing.T) {
297297
tt := table[i]
298298
if tt.eq {
299+
if !tt.a.Equals(tt.b) {
300+
t.Errorf("oops, a != b: %#v, %#v", tt.a, tt.b)
301+
}
299302
if tt.a.Less(tt.b) {
300303
t.Errorf("oops, a < b: %#v, %#v", tt.a, tt.b)
301304
}

value/value.go

+85-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,60 @@ type Value struct {
3636

3737
// Equals returns true iff the two values are equal.
3838
func (v Value) Equals(rhs Value) bool {
39-
return !v.Less(rhs) && !rhs.Less(v)
39+
if v.IntValue != nil && rhs.IntValue != nil {
40+
return *v.IntValue == *rhs.IntValue
41+
}
42+
if v.FloatValue != nil || rhs.FloatValue != nil {
43+
lf := float64(0.0)
44+
if v.FloatValue != nil {
45+
lf = float64(*v.FloatValue)
46+
} else if v.IntValue != nil {
47+
lf = float64(*v.IntValue)
48+
} else {
49+
return false
50+
}
51+
rf := 0.0
52+
if rhs.FloatValue != nil {
53+
rf = float64(*rhs.FloatValue)
54+
} else if rhs.IntValue != nil {
55+
rf = float64(*rhs.IntValue)
56+
} else {
57+
return false
58+
}
59+
return lf == rf
60+
}
61+
if v.StringValue != nil {
62+
if rhs.StringValue != nil {
63+
return *v.StringValue == *rhs.StringValue
64+
}
65+
return false
66+
}
67+
if v.BooleanValue != nil {
68+
if rhs.BooleanValue != nil {
69+
return *v.BooleanValue == *rhs.BooleanValue
70+
}
71+
return false
72+
}
73+
if v.ListValue != nil {
74+
if rhs.ListValue != nil {
75+
return v.ListValue.Equals(rhs.ListValue)
76+
}
77+
return false
78+
}
79+
if v.MapValue != nil {
80+
if rhs.MapValue != nil {
81+
return v.MapValue.Equals(rhs.MapValue)
82+
}
83+
return false
84+
}
85+
if v.Null {
86+
if rhs.Null {
87+
return true
88+
}
89+
return false
90+
}
91+
// No field is set, on either objects.
92+
return true
4093
}
4194

4295
// Less provides a total ordering for Value (so that they can be sorted, even
@@ -187,6 +240,20 @@ type List struct {
187240
Items []Value
188241
}
189242

243+
// Equals compares two lists lexically.
244+
func (l *List) Equals(rhs *List) bool {
245+
if len(l.Items) != len(rhs.Items) {
246+
return false
247+
}
248+
249+
for i, lv := range l.Items {
250+
if !lv.Equals(rhs.Items[i]) {
251+
return false
252+
}
253+
}
254+
return true
255+
}
256+
190257
// Less compares two lists lexically.
191258
func (l *List) Less(rhs *List) bool {
192259
i := 0
@@ -244,6 +311,23 @@ func (m *Map) computeOrder() []int {
244311
return m.order
245312
}
246313

314+
// Equals compares two maps lexically.
315+
func (m *Map) Equals(rhs *Map) bool {
316+
if len(m.Items) != len(rhs.Items) {
317+
return false
318+
}
319+
for _, lfield := range m.Items {
320+
rfield, ok := rhs.Get(lfield.Name)
321+
if !ok {
322+
return false
323+
}
324+
if !lfield.Value.Equals(rfield.Value) {
325+
return false
326+
}
327+
}
328+
return true
329+
}
330+
247331
// Less compares two maps lexically.
248332
func (m *Map) Less(rhs *Map) bool {
249333
var noAllocL, noAllocR [2]int

0 commit comments

Comments
 (0)