mirror of
https://github.com/tailscale/tailscale.git
synced 2025-05-01 13:11:01 +00:00
types/views: optimize SliceEqualAnyOrderFunc for small slices
If the total number of differences is less than a small amount, just do the dumb quadratic thing and compare every single object instead of allocating a map. Updates tailscale/corp#25479 Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: I8931b4355a2da4ec0f19739927311cf88711a840
This commit is contained in:
parent
7fa07f3416
commit
6ddeae7556
@ -381,6 +381,29 @@ func SliceEqualAnyOrderFunc[T any, V comparable](a, b Slice[T], cmp func(T) V) b
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For a small number of items, avoid the allocation of a map and just
|
||||||
|
// do the quadratic thing. We can also only check the items between
|
||||||
|
// diffStart and the end.
|
||||||
|
nRemain := a.Len() - diffStart
|
||||||
|
if nRemain <= 5 {
|
||||||
|
maxLen := a.Len() // same as b.Len()
|
||||||
|
for i := diffStart; i < maxLen; i++ {
|
||||||
|
av := cmp(a.At(i))
|
||||||
|
found := false
|
||||||
|
for j := diffStart; j < maxLen; j++ {
|
||||||
|
bv := cmp(b.At(j))
|
||||||
|
if av == bv {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// count the occurrences of remaining values and compare
|
// count the occurrences of remaining values and compare
|
||||||
valueCount := make(map[V]int)
|
valueCount := make(map[V]int)
|
||||||
for i, n := diffStart, a.Len(); i < n; i++ {
|
for i, n := diffStart, a.Len(); i < n; i++ {
|
||||||
|
@ -188,6 +188,15 @@ func TestSliceEqualAnyOrderFunc(t *testing.T) {
|
|||||||
|
|
||||||
// Nothing shared
|
// Nothing shared
|
||||||
c.Check(SliceEqualAnyOrderFunc(v, ncFrom("baz", "qux"), cmp), qt.Equals, false)
|
c.Check(SliceEqualAnyOrderFunc(v, ncFrom("baz", "qux"), cmp), qt.Equals, false)
|
||||||
|
|
||||||
|
// Long slice that matches
|
||||||
|
longSlice := ncFrom("a", "b", "c", "d", "e", "f", "g", "h", "i", "j")
|
||||||
|
longSame := ncFrom("b", "a", "c", "d", "e", "f", "g", "h", "i", "j") // first 2 elems swapped
|
||||||
|
c.Check(SliceEqualAnyOrderFunc(longSlice, longSame, cmp), qt.Equals, true)
|
||||||
|
|
||||||
|
// Long difference; past the quadratic limit
|
||||||
|
longDiff := ncFrom("b", "a", "c", "d", "e", "f", "g", "h", "i", "k") // differs at end
|
||||||
|
c.Check(SliceEqualAnyOrderFunc(longSlice, longDiff, cmp), qt.Equals, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSliceEqual(t *testing.T) {
|
func TestSliceEqual(t *testing.T) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user