From 5d777f84ad1f4e719590bdb1f343eed6d2a09f24 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 10 Dec 2024 16:07:32 -0600 Subject: [PATCH] scripts: Use depth to limit recursive result collection If we're not using these results, no reason to collect all of the children. Note that we still need to recurse for other measurements (limit, struct size, etc). This has a measurable, but small, impact on runtime: stack.py -z0 -Y: 0.202s stack.py -z1 -Y: 0.162s (~-19.8%) ctx.py -z0 -Y: 0.112s ctx.py -z1 -Y: 0.098s (~-12.5%) --- scripts/ctx.py | 14 +++++++++----- scripts/stack.py | 11 ++++++++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/scripts/ctx.py b/scripts/ctx.py index 68130359..017990e5 100755 --- a/scripts/ctx.py +++ b/scripts/ctx.py @@ -583,6 +583,7 @@ def collect_dwarf_info(obj_path, tags=None, *, def collect(obj_paths, *, sources=None, everything=False, + depth=1, **args): results = [] for obj_path in obj_paths: @@ -678,10 +679,13 @@ def collect(obj_paths, *, return size # recursive+cached children finder - def childrenof(entry, seen=set()): + def childrenof(entry, depth, seen=set()): # found a cycle? stop here if entry.off in seen: return [], {'cycle detected'}, True + # stop here? + if depth < 1: + return [], set(), False # cached? if not hasattr(childrenof, 'cache'): childrenof.cache = {} @@ -708,7 +712,7 @@ def collect(obj_paths, *, name_ = type.name size_ = sizeof(type, seen | {entry.off}) children_, notes_, dirty_ = childrenof( - type, seen | {entry.off}) + type, depth-1, seen | {entry.off}) children.append(CtxResult(file_, name_, size_, children=children_, notes=notes_)) @@ -729,7 +733,7 @@ def collect(obj_paths, *, name_ = child.name size_ = sizeof(child, seen | {entry.off}) children_, notes_, dirty_ = childrenof( - child, seen | {entry.off}) + child, depth-1, seen | {entry.off}) children.append(CtxResult(file_, name_, size_, i=child.off, children=children_, @@ -753,7 +757,7 @@ def collect(obj_paths, *, and 'DW_AT_type' in entry): type = int(entry['DW_AT_type'].strip('<>'), 0) children, notes, dirty = childrenof( - info[type], seen | {entry.off}) + info[type], depth, seen | {entry.off}) # void? elif ('DW_AT_type' not in entry and 'DW_AT_byte_size' not in entry): @@ -815,7 +819,7 @@ def collect(obj_paths, *, size_ = sizeof(param) # find children, recursing if necessary - children_, notes_, _ = childrenof(param) + children_, notes_, _ = childrenof(param, depth-2) params.append(CtxResult(file_, name_, size_, i=param.off, diff --git a/scripts/stack.py b/scripts/stack.py index f4763641..0d534c5b 100755 --- a/scripts/stack.py +++ b/scripts/stack.py @@ -718,6 +718,7 @@ def collect_callgraph(ci_path, def collect(obj_paths, ci_paths, *, sources=None, everything=False, + depth=1, **args): # parse the callgraphs cg = {} @@ -764,10 +765,13 @@ def collect(obj_paths, ci_paths, *, return frame + limit # recursive+cached children finder - def childrenof(node, seen=set()): + def childrenof(node, depth, seen=set()): # found a cycle? stop here if node.name in seen: return [], {'cycle detected'}, True + # stop here? + if depth < 1: + return [], set(), False # cached? if not hasattr(childrenof, 'cache'): childrenof.cache = {} @@ -783,7 +787,8 @@ def collect(obj_paths, ci_paths, *, name_ = node_.name.split(':', 1)[-1] frame_ = frameof(node_) limit_ = limitof(node_, seen | {node.name}) - children_, notes_, dirty_ = childrenof(node_, seen | {node.name}) + children_, notes_, dirty_ = childrenof( + node_, depth-1, seen | {node.name}) children.append(StackResult(file_, name_, frame_, limit_, children=children_, notes=notes_)) @@ -854,7 +859,7 @@ def collect(obj_paths, ci_paths, *, name = sym.name frame = frameof(node) limit = limitof(node) - children, notes, _ = childrenof(node) + children, notes, _ = childrenof(node, depth-1) results.append(StackResult(file, name, frame, limit, children=children, notes=notes))