summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <daniel.silverstone@codethink.co.uk>2018-11-06 11:05:34 +0000
committerDaniel Silverstone <daniel.silverstone@codethink.co.uk>2019-02-12 15:12:30 +0000
commitcda03313c85592dd30a57cf76c82e963208eba44 (patch)
tree2fea747f3a6743a7fffd3b358b6564215f63a1e7
parenta39c476711c875b87d10e0a8799c6d9a9973e5ce (diff)
downloadbuildstream-cda03313c85592dd30a57cf76c82e963208eba44.tar.gz
_yaml.py: Reduce use of `isinstance()` in `node_sanitize()`
We know that nodes are typically one of: str, list, dict, bool, tuple, NoneType or our ChainMap Of these, dict and ChainMap are Mapping, only list is list and the rest are returned unchanged. We can reduce/defer our use of isinstance here, dramatically, improving performance. Signed-off-by: Daniel Silverstone <daniel.silverstone@codethink.co.uk>
-rw-r--r--buildstream/_yaml.py24
1 files changed, 21 insertions, 3 deletions
diff --git a/buildstream/_yaml.py b/buildstream/_yaml.py
index d0fb502f5..9918e4241 100644
--- a/buildstream/_yaml.py
+++ b/buildstream/_yaml.py
@@ -914,6 +914,10 @@ RoundTripRepresenter.add_representer(SanitizedDict,
SafeRepresenter.represent_dict)
+# Types we can short-circuit in node_sanitize for speed.
+__SANITIZE_SHORT_CIRCUIT_TYPES = (int, float, str, bool, tuple)
+
+
# node_sanitize()
#
# Returnes an alphabetically ordered recursive copy
@@ -922,9 +926,21 @@ RoundTripRepresenter.add_representer(SanitizedDict,
# Only dicts are ordered, list elements are left in order.
#
def node_sanitize(node):
+ # Short-circuit None which occurs ca. twice per element
+ if node is None:
+ return node
+
+ node_type = type(node)
+ # Next short-circuit integers, floats, strings, booleans, and tuples
+ if node_type in __SANITIZE_SHORT_CIRCUIT_TYPES:
+ return node
+ # Now short-circuit lists. Note this is only for the raw list
+ # type, CommentedSeq and others get caught later.
+ elif node_type is list:
+ return [node_sanitize(elt) for elt in node]
- if isinstance(node, collections.abc.Mapping):
-
+ # Finally ChainMap and dict, and other Mappings need special handling
+ if node_type in (dict, ChainMap) or isinstance(node, collections.Mapping):
result = SanitizedDict()
key_list = [key for key, _ in node_items(node)]
@@ -932,10 +948,12 @@ def node_sanitize(node):
result[key] = node_sanitize(node[key])
return result
-
+ # Catch the case of CommentedSeq and friends. This is more rare and so
+ # we keep complexity down by still using isinstance here.
elif isinstance(node, list):
return [node_sanitize(elt) for elt in node]
+ # Everything else (such as commented scalars) just gets returned as-is.
return node