osdict: lazy load data from libosinfo

I've noticed that virt-manager took more time to startup after we
started reading OSes data from libosinfo.

Now the libosinfo data is loaded the first time it is accessed,
without pre-loading it.

This could be further improved by not loading completely an _OsVariant
object but only the data that is requested.

With the lazy load optimization (best of 10 attempts):

$ echo yes | time ./virt-xml --connect __virtinst_test__test:////home/gscrivano/src/virt-manager/tests/testdriver.xml,predictable --confirm test --edit --cpu host-passthrough > /dev/null
0.13user 0.02system 0:00.22elapsed 74%CPU (0avgtext+0avgdata 26756maxresident)k

Without (best of 10 attempts):

$ echo yes | time ./virt-xml --connect __virtinst_test__test:////home/gscrivano/src/virt-manager/tests/testdriver.xml,predictable --confirm test --edit --cpu host-passthrough > /dev/null
1.26user 0.04system 0:01.36elapsed 95%CPU (0avgtext+0avgdata 57996maxresident)k
0inputs+16outputs (0major+17499minor)pagefaults 0swaps

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2014-03-28 11:41:20 +01:00
parent 58d8795b27
commit 5120b90fc3
1 changed files with 87 additions and 66 deletions

View File

@ -24,9 +24,6 @@ _allvariants = {}
from datetime import datetime
from gi.repository import Libosinfo as libosinfo # pylint: disable=E0611
loader = libosinfo.Loader()
loader.process_default_path()
_aliases = {
"altlinux" : "altlinux1.0",
"debianetch" : "debian4",
@ -67,14 +64,6 @@ _aliases = {
}
def lookup_os(key):
key = _aliases.get(key) or key
ret = _allvariants.get(key)
if ret is None:
return ret
return ret
def _sort(tosort, sortpref=None):
sortby_mappings = {}
distro_mappings = {}
@ -122,56 +111,6 @@ def _sort(tosort, sortpref=None):
return retlist
def list_os(list_types=False, typename=None,
filtervars=None, only_supported=False,
**kwargs):
sortmap = {}
filtervars = filtervars or []
for key, osinfo in _allvariants.items():
if list_types and not osinfo.is_type:
continue
if not list_types and osinfo.is_type:
continue
if typename and typename != osinfo.typename:
continue
if filtervars:
filtervars = [lookup_os(x).name for x in filtervars]
if osinfo.name not in filtervars:
continue
if only_supported and not osinfo.supported:
continue
sortmap[key] = osinfo
return _sort(sortmap, **kwargs)
def lookup_osdict_key(variant, key, default):
val = _SENTINEL
if variant is not None:
if not hasattr(lookup_os(variant), key):
raise ValueError("Unknown osdict property '%s'" % key)
val = getattr(lookup_os(variant), key)
if val == _SENTINEL:
val = default
return val
def get_recommended_resources(variant, arch):
v = _allvariants.get(variant)
if v is None:
return None
return v.get_recommended_resources(arch)
def lookup_os_by_media(location):
media = libosinfo.Media.create_from_location(location, None)
ret = loader.get_db().guess_os_from_media(media)
if ret and len(ret) > 0:
return ret[0].get_short_id()
return None
class _OSVariant(object):
"""
Object tracking guest OS specific configuration bits.
@ -569,9 +508,91 @@ _add_type("unix", "UNIX")
_add_type("other", "Other")
_add_var("generic", "Generic", supported=True, parent="other")
db = loader.get_db()
oslist = db.get_os_list()
for os in range(oslist.get_length()):
osi = _OsVariantOsInfo(oslist.get_nth(os))
_allvariants[osi.name] = osi
_os_data_loaded = False
_os_loader = None
def _get_os_loader():
global _os_loader
if _os_loader:
return _os_loader
_os_loader = libosinfo.Loader()
_os_loader.process_default_path()
return _os_loader
def _load_os_data():
global _os_data_loaded
if _os_data_loaded:
return
loader = _get_os_loader()
db = loader.get_db()
oslist = db.get_os_list()
for os in range(oslist.get_length()):
osi = _OsVariantOsInfo(oslist.get_nth(os))
_allvariants[osi.name] = osi
_os_data_loaded = True
def lookup_os(key):
_load_os_data()
key = _aliases.get(key) or key
ret = _allvariants.get(key)
if ret is None:
return ret
return ret
def list_os(list_types=False, typename=None,
filtervars=None, only_supported=False,
**kwargs):
_load_os_data()
sortmap = {}
filtervars = filtervars or []
for key, osinfo in _allvariants.items():
if list_types and not osinfo.is_type:
continue
if not list_types and osinfo.is_type:
continue
if typename and typename != osinfo.typename:
continue
if filtervars:
filtervars = [lookup_os(x).name for x in filtervars]
if osinfo.name not in filtervars:
continue
if only_supported and not osinfo.supported:
continue
sortmap[key] = osinfo
return _sort(sortmap, **kwargs)
def lookup_osdict_key(variant, key, default):
_load_os_data()
val = _SENTINEL
if variant is not None:
if not hasattr(lookup_os(variant), key):
raise ValueError("Unknown osdict property '%s'" % key)
val = getattr(lookup_os(variant), key)
if val == _SENTINEL:
val = default
return val
def get_recommended_resources(variant, arch):
_load_os_data()
v = _allvariants.get(variant)
if v is None:
return None
return v.get_recommended_resources(arch)
def lookup_os_by_media(location):
loader = _get_os_loader()
media = libosinfo.Media.create_from_location(location, None)
ret = loader.get_db().guess_os_from_media(media)
if ret and len(ret) > 0:
return ret[0].get_short_id()
return None