From cff46eee671f8c7881323655d6443c6691852930 Mon Sep 17 00:00:00 2001 From: pascal Date: Thu, 6 Aug 2026 12:49:36 +0200 Subject: [PATCH] introduce peerGroupsIdx to avoid looping through the groups to figure out peer membership --- .../networkmap/networkmapcompute.go | 37 +++++++++++++------ .../management/networkmap/networkmapdata.go | 5 +++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/shared/management/networkmap/networkmapcompute.go b/shared/management/networkmap/networkmapcompute.go index f07ff0ba1..dedfaaedd 100644 --- a/shared/management/networkmap/networkmapcompute.go +++ b/shared/management/networkmap/networkmapcompute.go @@ -199,12 +199,9 @@ func (nmd *NetworkMapData) getPeersGroupsPoliciesRoutes( relevantPeerIDs[peerID] = nmd.Peers[peerID] - peerGroupSet := make(map[string]struct{}, 8) - for groupID, group := range nmd.Groups { - if slices.Contains(group.Peers, peerID) { - relevantGroupIDs[groupID] = group - peerGroupSet[groupID] = struct{}{} - } + peerGroupSet := nmd.GetPeerGroups(peerID) + for groupID := range peerGroupSet { + relevantGroupIDs[groupID] = nmd.Groups[groupID] } routeAccessControlGroups := make(map[string]struct{}) @@ -520,14 +517,32 @@ func (nmd *NetworkMapData) forcesRoutingPeerDNSResolution(peerID string) bool { return false } +// GetPeerGroups returns the set of group IDs the peer belongs to. The +// underlying peer→groups index is built once per NetworkMapData and the +// returned set is shared — callers must not mutate it. func (nmd *NetworkMapData) GetPeerGroups(peerID string) map[string]struct{} { - groups := make(map[string]struct{}) - for groupID, group := range nmd.Groups { - if slices.Contains(group.Peers, peerID) { - groups[groupID] = struct{}{} + nmd.peerGroupsOnce.Do(func() { + idx := make(map[string]map[string]struct{}, len(nmd.Peers)) + for groupID, group := range nmd.Groups { + if group == nil { + continue + } + for _, pid := range group.Peers { + set, ok := idx[pid] + if !ok { + set = make(map[string]struct{}) + idx[pid] = set + } + set[groupID] = struct{}{} + } } + nmd.peerGroupsIdx = idx + }) + + if set, ok := nmd.peerGroupsIdx[peerID]; ok { + return set } - return groups + return map[string]struct{}{} } func (nmd *NetworkMapData) getUniquePeerIDsFromGroupsIDs(groups []string) []string { diff --git a/shared/management/networkmap/networkmapdata.go b/shared/management/networkmap/networkmapdata.go index 71bb0ba96..e874752d2 100644 --- a/shared/management/networkmap/networkmapdata.go +++ b/shared/management/networkmap/networkmapdata.go @@ -1,6 +1,8 @@ package networkmap import ( + "sync" + "github.com/netbirdio/netbird/shared/management/networkmap/nmdata" ) @@ -39,6 +41,9 @@ type NetworkMapData struct { //nolint:revive // established name across the code AppliedZoneCandidates []AppliedZoneCandidate PrivateServiceCandidates []PrivateServiceCandidate + + peerGroupsOnce sync.Once + peerGroupsIdx map[string]map[string]struct{} } // AppliedZoneCandidate is an account-level custom DNS zone reduced to the