From 0cfca436f1a2951df7c33fbe64908664ad0c1014 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Fri, 7 Aug 2026 01:10:11 -0700 Subject: [PATCH] perf(weed/topology): size the new-volume list from the actual delta (#10613) A reconnecting volume server reports every volume it has as new, so newVolumes grew from nil to one entry per volume, reallocating and copying its way there. Sizing it to len(actualVolumes) instead would allocate the whole list on every steady-state heartbeat, where nothing is new. After the deletion pass everything left on the node is also in this heartbeat, so the difference is exactly what the node is about to gain: all of them on a reconnect, none in steady state. First registration of 550k volumes 1041.7 MB -> 667.4 MB --- weed/topology/data_node.go | 8 ++++++++ weed/topology/disk.go | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/weed/topology/data_node.go b/weed/topology/data_node.go index a1ad201a9..b3f2edda9 100644 --- a/weed/topology/data_node.go +++ b/weed/topology/data_node.go @@ -86,6 +86,7 @@ func (dn *DataNode) UpdateVolumes(actualVolumes []storage.VolumeInfo) (newVolume dn.Lock() defer dn.Unlock() + keptCount := 0 for _, c := range dn.children { disk := c.(*Disk) for _, v := range disk.RemoveVolumesNotIn(actualVolumeIds) { @@ -102,6 +103,13 @@ func (dn *DataNode) UpdateVolumes(actualVolumes []storage.VolumeInfo) (newVolume } disk.UpAdjustDiskUsageDelta(types.ToDiskType(v.DiskType), deltaDiskUsage) } + keptCount += disk.VolumeCount() + } + // Everything still on the node is also in this heartbeat, so the remainder + // is what the node is about to gain. A steady-state heartbeat gains nothing + // and must not allocate here; a reconnecting server gains all of them. + if addedCount := len(actualVolumes) - keptCount; addedCount > 0 { + newVolumes = make([]storage.VolumeInfo, 0, addedCount) } for _, v := range actualVolumes { isNew, isChanged := dn.doAddOrUpdateVolume(v) diff --git a/weed/topology/disk.go b/weed/topology/disk.go index ef5ee0b58..f2bd0f9f2 100644 --- a/weed/topology/disk.go +++ b/weed/topology/disk.go @@ -212,6 +212,12 @@ func (d *Disk) GetVolumes() (ret []storage.VolumeInfo) { return ret } +func (d *Disk) VolumeCount() int { + d.RLock() + defer d.RUnlock() + return len(d.volumes) +} + // RemoveVolumesNotIn drops the volumes whose ids are absent from keep and // returns them, so a heartbeat can be diffed without first copying the whole // volume map out.