Skip to content

Commit 0f5fdda

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Perf: Use dicts for ProviderTree roots" into stable/stein
2 parents 4f9023e + 754d8eb commit 0f5fdda

File tree

3 files changed

+34
-10
lines changed

3 files changed

+34
-10
lines changed

nova/compute/provider_tree.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from oslo_concurrency import lockutils
2626
from oslo_log import log as logging
2727
from oslo_utils import uuidutils
28+
import six
2829

2930
from nova.i18n import _
3031

@@ -232,7 +233,12 @@ class ProviderTree(object):
232233
def __init__(self):
233234
"""Create an empty provider tree."""
234235
self.lock = lockutils.internal_lock(_LOCK_NAME)
235-
self.roots = []
236+
self.roots_by_uuid = {}
237+
self.roots_by_name = {}
238+
239+
@property
240+
def roots(self):
241+
return six.itervalues(self.roots_by_uuid)
236242

237243
def get_provider_uuids(self, name_or_uuid=None):
238244
"""Return a list, in top-down traversable order, of the UUIDs of all
@@ -343,7 +349,8 @@ def populate_from_iterable(self, provider_dicts):
343349

344350
provider = _Provider.from_dict(pd)
345351
if parent_uuid is None:
346-
self.roots.append(provider)
352+
self.roots_by_uuid[provider.uuid] = provider
353+
self.roots_by_name[provider.name] = provider
347354
else:
348355
parent = self._find_with_lock(parent_uuid)
349356
parent.add_child(provider)
@@ -357,7 +364,8 @@ def _remove_with_lock(self, name_or_uuid):
357364
parent = self._find_with_lock(found.parent_uuid)
358365
parent.remove_child(found)
359366
else:
360-
self.roots.remove(found)
367+
del self.roots_by_uuid[found.uuid]
368+
del self.roots_by_name[found.name]
361369

362370
def remove(self, name_or_uuid):
363371
"""Safely removes the provider identified by the supplied name_or_uuid
@@ -393,10 +401,21 @@ def new_root(self, name, uuid, generation=None):
393401
raise ValueError(err % uuid)
394402

395403
p = _Provider(name, uuid=uuid, generation=generation)
396-
self.roots.append(p)
404+
self.roots_by_uuid[uuid] = p
405+
self.roots_by_name[name] = p
397406
return p.uuid
398407

399408
def _find_with_lock(self, name_or_uuid, return_root=False):
409+
# Optimization for large number of roots (e.g. ironic): if name_or_uuid
410+
# represents a root, this is O(1).
411+
found = self.roots_by_uuid.get(name_or_uuid)
412+
if found:
413+
return found
414+
found = self.roots_by_name.get(name_or_uuid)
415+
if found:
416+
return found
417+
418+
# Okay, it's a child; do it the hard way.
400419
for root in self.roots:
401420
found = root.find(name_or_uuid)
402421
if found:

nova/tests/unit/virt/libvirt/test_driver.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21490,7 +21490,8 @@ def test_allocate_mdevs_with_no_gpu_capacity(self,
2149021490
self.assertRaises(exception.ComputeResourcesUnavailable,
2149121491
drvr._allocate_mdevs, allocations=allocations)
2149221492

21493-
def test_allocate_mdevs_with_no_idea_of_the_provider(self):
21493+
@mock.patch.object(libvirt_driver.LOG, 'warning')
21494+
def test_allocate_mdevs_with_no_idea_of_the_provider(self, mock_warning):
2149421495
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
2149521496
# Mock the fact update_provider_tree() should have run
2149621497
drvr.provider_tree = self._get_fake_provider_tree_with_vgpu()
@@ -21517,6 +21518,9 @@ def test_allocate_mdevs_with_no_idea_of_the_provider(self):
2151721518
# Remember, rp2 has a wrong naming convention
2151821519
self.assertRaises(exception.ComputeResourcesUnavailable,
2151921520
drvr._allocate_mdevs, allocations=allocations)
21521+
mock_warning.assert_called_once_with(
21522+
"pGPU device name %(name)s can't be guessed from the ProviderTree "
21523+
"roots %(roots)s", {'name': 'oops_I_did_it_again', 'roots': 'cn'})
2152021524

2152121525
@mock.patch.object(libvirt_driver.LibvirtDriver, '_get_mediated_devices')
2152221526
@mock.patch.object(libvirt_driver.LibvirtDriver,

nova/virt/libvirt/driver.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6366,18 +6366,19 @@ def _allocate_mdevs(self, allocations):
63666366
rp_name = allocated_rp.name
63676367
# There can be multiple roots, we need to find the root name
63686368
# to guess the physical device name
6369-
roots = self.provider_tree.roots
6369+
roots = list(self.provider_tree.roots)
63706370
for root in roots:
63716371
if rp_name.startswith(root.name + '_'):
63726372
# The RP name convention is :
63736373
# root_name + '_' + parent_device
63746374
parent_device = rp_name[len(root.name) + 1:]
63756375
break
63766376
else:
6377-
LOG.warning("pGPU device name %(name)s can't be guessed from "
6378-
"the ProviderTree "
6379-
"roots %(roots)s", {'name': rp_name,
6380-
'roots': roots})
6377+
LOG.warning(
6378+
"pGPU device name %(name)s can't be guessed from the "
6379+
"ProviderTree roots %(roots)s",
6380+
{'name': rp_name,
6381+
'roots': ', '.join([root.name for root in roots])})
63816382
# We f... have no idea what was the parent device
63826383
# If we can't find devices having available VGPUs, just raise
63836384
raise exception.ComputeResourcesUnavailable(

0 commit comments

Comments
 (0)