Remove ProviderIds namedtuple

It turns out that all the callers of methods that return ProviderIds
access the data using attributes that are already present on the object
provided by a sql alchemy RowProxy object (which is the result of
iterating a ResultProxy object, returned by sqla.execute()). Creating
a namedtuple is redundant and adds some processing cost [1].

However, the AnchorIds namedtuple used in the same file _is_ necessary
because it provides a hashable type required by the set that wraps
the collection of AnchorIds.

The other user of namedtuple, RPCandidate, in
placement/objects/rp_candidates.py has a specific interface for which
a namedtuple is correct.

[1] provider_ids_from_rp_ids was identified as being a major contributor
when doing performance profiling. Most of the cost is executing with the
database, but the tuple creation is a factor.

Change-Id: I1e1522eae7b4360cf57c34164612ae228fad14a3
This commit is contained in:
Chris Dent 2019-07-31 12:34:30 +01:00 committed by Eric Fried
parent d04168088c
commit 8626b6517b

View File

@ -37,8 +37,6 @@ _RP_TRAIT_TBL = models.ResourceProviderTrait.__table__
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
ProviderIds = collections.namedtuple(
'ProviderIds', 'id uuid parent_id parent_uuid root_id root_uuid')
AnchorIds = collections.namedtuple( AnchorIds = collections.namedtuple(
'AnchorIds', 'rp_id rp_uuid anchor_id anchor_uuid') 'AnchorIds', 'rp_id rp_uuid anchor_id anchor_uuid')
@ -302,10 +300,9 @@ class RequestWideSearchContext(object):
def provider_ids_from_rp_ids(context, rp_ids): def provider_ids_from_rp_ids(context, rp_ids):
"""Given an iterable of internal resource provider IDs, returns a dict, """Given an iterable of internal resource provider IDs, returns a dict,
keyed by internal provider Id, of ProviderIds namedtuples describing those keyed by internal provider Id, of sqla objects describing those providers.
providers.
:returns: dict, keyed by internal provider Id, of ProviderIds namedtuples :returns: dict, keyed by internal provider Id, of sqla objects
:param rp_ids: iterable of internal provider IDs to look up :param rp_ids: iterable of internal provider IDs to look up
""" """
# SELECT # SELECT
@ -338,18 +335,18 @@ def provider_ids_from_rp_ids(context, rp_ids):
ret = {} ret = {}
for r in context.session.execute(sel): for r in context.session.execute(sel):
ret[r['id']] = ProviderIds(**r) ret[r['id']] = r
return ret return ret
@db_api.placement_context_manager.reader @db_api.placement_context_manager.reader
def provider_ids_from_uuid(context, uuid): def provider_ids_from_uuid(context, uuid):
"""Given the UUID of a resource provider, returns a namedtuple """Given the UUID of a resource provider, returns a sqlalchemy object with
(ProviderIds) with the internal ID, the UUID, the parent provider's the internal ID, the UUID, the parent provider's internal ID, parent
internal ID, parent provider's UUID, the root provider's internal ID and provider's UUID, the root provider's internal ID and the root provider
the root provider UUID. UUID.
:returns: ProviderIds object containing the internal IDs and UUIDs of the :returns: sqlalchemy object containing the internal IDs and UUIDs of the
provider identified by the supplied UUID provider identified by the supplied UUID
:param uuid: The UUID of the provider to look up :param uuid: The UUID of the provider to look up
""" """
@ -382,7 +379,7 @@ def provider_ids_from_uuid(context, uuid):
res = context.session.execute(sel).fetchone() res = context.session.execute(sel).fetchone()
if not res: if not res:
return None return None
return ProviderIds(**dict(res)) return res
def _usage_select(rc_ids): def _usage_select(rc_ids):