diff options
author | Daniel Silverstone <daniel.silverstone@codethink.co.uk> | 2018-11-06 11:05:34 +0000 |
---|---|---|
committer | Daniel Silverstone <daniel.silverstone@codethink.co.uk> | 2019-02-12 15:12:30 +0000 |
commit | cda03313c85592dd30a57cf76c82e963208eba44 (patch) | |
tree | 2fea747f3a6743a7fffd3b358b6564215f63a1e7 | |
parent | a39c476711c875b87d10e0a8799c6d9a9973e5ce (diff) | |
download | buildstream-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.py | 24 |
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 |