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:
Andrew Dunham
2025-01-09 16:55:07 -05:00
parent 7fa07f3416
commit 6ddeae7556
2 changed files with 32 additions and 0 deletions

View File

@@ -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++ {