mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-11-08 13:07:45 +01: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:
1 parent
3fce1a938d
commit
2ec899bdee
2 files changed
+21
-10
No files matched your search
@@ -78,22 +78,18 @@ func (dn *DataNode) doAddOrUpdateVolume(v storage.VolumeInfo) (isNew, isChanged
|
|||||||
// used in master to notify master clients of these changes.
|
// used in master to notify master clients of these changes.
|
||||||
func (dn *DataNode) UpdateVolumes(actualVolumes []storage.VolumeInfo) (newVolumes, deletedVolumes, changedVolumes []storage.VolumeInfo) {
|
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 {
|
for _, v := range actualVolumes {
|
||||||
actualVolumeMap[v.Id] = v
|
actualVolumeIds[v.Id] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
dn.Lock()
|
dn.Lock()
|
||||||
defer dn.Unlock()
|
defer dn.Unlock()
|
||||||
|
|
||||||
existingVolumes := dn.getVolumes()
|
for _, c := range dn.children {
|
||||||
|
disk := c.(*Disk)
|
||||||
for _, v := range existingVolumes {
|
for _, v := range disk.RemoveVolumesNotIn(actualVolumeIds) {
|
||||||
vid := v.Id
|
glog.V(0).Infoln("Deleting volume id:", v.Id)
|
||||||
if _, ok := actualVolumeMap[vid]; !ok {
|
|
||||||
glog.V(0).Infoln("Deleting volume id:", vid)
|
|
||||||
disk := dn.getOrCreateDisk(v.DiskType)
|
|
||||||
disk.DeleteVolumeById(vid)
|
|
||||||
deletedVolumes = append(deletedVolumes, v)
|
deletedVolumes = append(deletedVolumes, v)
|
||||||
|
|
||||||
deltaDiskUsage := &DiskUsageCounts{}
|
deltaDiskUsage := &DiskUsageCounts{}
|
||||||
|
|||||||
@@ -211,6 +211,21 @@ func (d *Disk) GetVolumes() (ret []storage.VolumeInfo) {
|
|||||||
return ret
|
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) {
|
func (d *Disk) GetVolumesById(id needle.VolumeId) (storage.VolumeInfo, error) {
|
||||||
d.RLock()
|
d.RLock()
|
||||||
defer d.RUnlock()
|
defer d.RUnlock()
|
||||||
|
|||||||
Reference in new issue
Block a user