Skip to content

Commit

Permalink
Speed up ScanVGs by only scanning PVs and LVs at most once.
Browse files Browse the repository at this point in the history
Instead of making calls to ScanPVs and ScanLVs when walking the
response from ScanVGs, we only do those once.

The ScanPV call is very slow if there are a lot of block devices
(including lvm block devices).

Overall, this results in considerable speedup.

                 |  vm  | hardware
     with-change | 1.22 | 1.35
     without     | 1.74 | 2.99

They're by no means scientific numbers, but it is a considerable win.
  • Loading branch information
Scott Moser authored and rchamarthy committed Apr 9, 2020
1 parent d2eda4f commit 6591a09
Showing 1 changed file with 44 additions and 11 deletions.
55 changes: 44 additions & 11 deletions linux/lvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ func (ls *linuxLVM) scanVGs(filter disko.VGFilter, scanArgs ...string) (disko.VG
return vgs, err
}

if len(vgdatum) == 0 {
return vgs, err
}

for _, vgd := range vgdatum {
name := vgd.Name
vg := disko.VG{
Expand All @@ -66,23 +70,52 @@ func (ls *linuxLVM) scanVGs(filter disko.VGFilter, scanArgs ...string) (disko.VG
continue
}

pvs, err := ls.ScanPVs(func(p disko.PV) bool { return p.VGName == name })
if err != nil {
return vgs, err
}
vgs[name] = vg
}

lvs, err := ls.scanLVs(func(d disko.LV) bool { return true }, name)
if err != nil {
return vgs, err
if len(vgs) == 0 {
return vgs, nil
}

fullVgs := disko.VGSet{}
lvSetsByVG := map[string]disko.LVSet{}
pvSetsByVG := map[string]disko.PVSet{}

lvs, err := ls.scanLVs(func(d disko.LV) bool { return true })

if err != nil {
return vgs, err
}

for _, lv := range lvs {
if _, ok := lvSetsByVG[lv.VGName]; ok {
lvSetsByVG[lv.VGName][lv.Name] = lv
} else {
lvSetsByVG[lv.VGName] = disko.LVSet{lv.Name: lv}
}
}

vg.PVs = pvs
vg.Volumes = lvs
pvs, err := ls.scanPVs(func(d disko.PV) bool { return true })

vgs[name] = vg
if err != nil {
return vgs, err
}

for _, pv := range pvs {
if _, ok := pvSetsByVG[pv.VGName]; ok {
pvSetsByVG[pv.VGName][pv.Name] = pv
} else {
pvSetsByVG[pv.VGName] = disko.PVSet{pv.Name: pv}
}
}

for _, vg := range vgs {
vg.PVs = pvSetsByVG[vg.Name]
vg.Volumes = lvSetsByVG[vg.Name]
fullVgs[vg.Name] = vg
}

return vgs, nil
return fullVgs, nil
}

func (ls *linuxLVM) ScanLVs(filter disko.LVFilter) (disko.LVSet, error) {
Expand Down

0 comments on commit 6591a09

Please sign in to comment.