mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-16 04:06:44 +00:00
perf(weed/topology): diff a heartbeat without copying the volume map (#10608)
* perf(weed/topology): keep only volume ids in the heartbeat membership set The map is used solely to test whether a known volume is still present, but it copied the whole 152-byte VolumeInfo for every volume in the heartbeat. Presize it too, since the count is known. BenchmarkSyncDataNodeRegistration/100000Volumes 199670102 B/op -> 180157310 B/op * perf(weed/topology): diff a heartbeat without copying the volume map To find volumes the data node no longer reports, UpdateVolumes copied every VolumeInfo on the node into a fresh slice, then deleted the missing ones one at a time. At 100k volumes that is a 15MB copy per heartbeat to usually find nothing. Scan the disk maps in place instead and return only what was removed. BenchmarkSyncDataNodeRegistration/100000Volumes 180157310 B/op -> 87806436 B/op
This commit is contained in:
@@ -78,22 +78,18 @@ func (dn *DataNode) doAddOrUpdateVolume(v storage.VolumeInfo) (isNew, isChanged
|
||||
// used in master to notify master clients of these changes.
|
||||
func (dn *DataNode) UpdateVolumes(actualVolumes []storage.VolumeInfo) (newVolumes, deletedVolumes, changedVolumes []storage.VolumeInfo) {
|
||||
|
||||
actualVolumeMap := make(map[needle.VolumeId]storage.VolumeInfo)
|
||||
actualVolumeIds := make(map[needle.VolumeId]struct{}, len(actualVolumes))
|
||||
for _, v := range actualVolumes {
|
||||
actualVolumeMap[v.Id] = v
|
||||
actualVolumeIds[v.Id] = struct{}{}
|
||||
}
|
||||
|
||||
dn.Lock()
|
||||
defer dn.Unlock()
|
||||
|
||||
existingVolumes := dn.getVolumes()
|
||||
|
||||
for _, v := range existingVolumes {
|
||||
vid := v.Id
|
||||
if _, ok := actualVolumeMap[vid]; !ok {
|
||||
glog.V(0).Infoln("Deleting volume id:", vid)
|
||||
disk := dn.getOrCreateDisk(v.DiskType)
|
||||
disk.DeleteVolumeById(vid)
|
||||
for _, c := range dn.children {
|
||||
disk := c.(*Disk)
|
||||
for _, v := range disk.RemoveVolumesNotIn(actualVolumeIds) {
|
||||
glog.V(0).Infoln("Deleting volume id:", v.Id)
|
||||
deletedVolumes = append(deletedVolumes, v)
|
||||
|
||||
deltaDiskUsage := &DiskUsageCounts{}
|
||||
|
||||
@@ -211,6 +211,21 @@ func (d *Disk) GetVolumes() (ret []storage.VolumeInfo) {
|
||||
return ret
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (d *Disk) RemoveVolumesNotIn(keep map[needle.VolumeId]struct{}) (removed []storage.VolumeInfo) {
|
||||
d.Lock()
|
||||
defer d.Unlock()
|
||||
for vid, v := range d.volumes {
|
||||
if _, ok := keep[vid]; !ok {
|
||||
removed = append(removed, v)
|
||||
delete(d.volumes, vid)
|
||||
}
|
||||
}
|
||||
return removed
|
||||
}
|
||||
|
||||
func (d *Disk) GetVolumesById(id needle.VolumeId) (storage.VolumeInfo, error) {
|
||||
d.RLock()
|
||||
defer d.RUnlock()
|
||||
|
||||
Reference in New Issue
Block a user