mirror of
https://github.com/tailscale/tailscale.git
synced 2025-05-01 05:01: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
|
||||
}
|
||||
|
||||
// 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
|
||||
valueCount := make(map[V]int)
|
||||
for i, n := diffStart, a.Len(); i < n; i++ {
|
||||
|
@ -188,6 +188,15 @@ func TestSliceEqualAnyOrderFunc(t *testing.T) {
|
||||
|
||||
// Nothing shared
|
||||
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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user