Skip to content

Commit 27fc32d

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Perf: Use dicts for ProviderTree roots"
2 parents de31466 + 8c79745 commit 27fc32d

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
@@ -21509,7 +21509,8 @@ def test_allocate_mdevs_with_no_gpu_capacity(self,
2150921509
self.assertRaises(exception.ComputeResourcesUnavailable,
2151021510
drvr._allocate_mdevs, allocations=allocations)
2151121511

21512-
def test_allocate_mdevs_with_no_idea_of_the_provider(self):
21512+
@mock.patch.object(libvirt_driver.LOG, 'warning')
21513+
def test_allocate_mdevs_with_no_idea_of_the_provider(self, mock_warning):
2151321514
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), True)
2151421515
# Mock the fact update_provider_tree() should have run
2151521516
drvr.provider_tree = self._get_fake_provider_tree_with_vgpu()
@@ -21536,6 +21537,9 @@ def test_allocate_mdevs_with_no_idea_of_the_provider(self):
2153621537
# Remember, rp2 has a wrong naming convention
2153721538
self.assertRaises(exception.ComputeResourcesUnavailable,
2153821539
drvr._allocate_mdevs, allocations=allocations)
21540+
mock_warning.assert_called_once_with(
21541+
"pGPU device name %(name)s can't be guessed from the ProviderTree "
21542+
"roots %(roots)s", {'name': 'oops_I_did_it_again', 'roots': 'cn'})
2153921543

2154021544
@mock.patch.object(libvirt_driver.LibvirtDriver, '_get_mediated_devices')
2154121545
@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
@@ -6462,18 +6462,19 @@ def _allocate_mdevs(self, allocations):
64626462
rp_name = allocated_rp.name
64636463
# There can be multiple roots, we need to find the root name
64646464
# to guess the physical device name
6465-
roots = self.provider_tree.roots
6465+
roots = list(self.provider_tree.roots)
64666466
for root in roots:
64676467
if rp_name.startswith(root.name + '_'):
64686468
# The RP name convention is :
64696469
# root_name + '_' + parent_device
64706470
parent_device = rp_name[len(root.name) + 1:]
64716471
break
64726472
else:
6473-
LOG.warning("pGPU device name %(name)s can't be guessed from "
6474-
"the ProviderTree "
6475-
"roots %(roots)s", {'name': rp_name,
6476-
'roots': roots})
6473+
LOG.warning(
6474+
"pGPU device name %(name)s can't be guessed from the "
6475+
"ProviderTree roots %(roots)s",
6476+
{'name': rp_name,
6477+
'roots': ', '.join([root.name for root in roots])})
64776478
# We f... have no idea what was the parent device
64786479
# If we can't find devices having available VGPUs, just raise
64796480
raise exception.ComputeResourcesUnavailable(

0 commit comments

Comments
 (0)