[gjs: 7/11] heapgraph: Allow selecting multiple targets
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 7/11] heapgraph: Allow selecting multiple targets
- Date: Sun, 18 Aug 2019 19:22:08 +0000 (UTC)
commit 02e250fd3d538191900ef7b516df09667cb560d7
Author: Philip Chimento <philip chimento gmail com>
Date: Sat Aug 10 13:08:50 2019 -0700
heapgraph: Allow selecting multiple targets
This allows specifying more than one target, such as:
heapgraph.py GObject Proxy -e _data
to select all GObject and Proxy objects, and additionally all nodes with
a property named "_data" and the property value.
tools/heapgraph.py | 89 ++++++++++++++++++++++++++++--------------------------
1 file changed, 47 insertions(+), 42 deletions(-)
---
diff --git a/tools/heapgraph.py b/tools/heapgraph.py
index 3b26673f..5a809a9e 100755
--- a/tools/heapgraph.py
+++ b/tools/heapgraph.py
@@ -31,24 +31,23 @@ parser = argparse.ArgumentParser(description='Find what is rooting or preventing
parser.add_argument('heap_file', metavar='FILE',
help='Garbage collector heap from System.dumpHeap()')
-parser.add_argument('target', metavar='TARGET',
+parser.add_argument('targets', metavar='TARGET', nargs='*',
help='Heap address (eg. 0x7fa814054d00) or type prefix (eg. Array, Object, GObject,
Function...)')
### Target Options
-targ_opts = parser.add_mutually_exclusive_group()
+targ_opts = parser.add_argument_group('Target options')
+targ_opts.add_argument('--edge', '-e', dest='edge_targets',
+ action='append', default=[],
+ help='Add an edge label to the list of targets')
-targ_opts.add_argument('--edge', '-e', dest='edge_target', action='store_true',
- default=False,
- help='Treat TARGET as an edge name')
+targ_opts.add_argument('--function', '-f', dest='func_targets',
+ action='append', default=[],
+ help='Add a function name to the list of targets')
-targ_opts.add_argument('--function', '-f', dest='func_target', action='store_true',
- default=False,
- help='Treat TARGET as a function name')
-
-targ_opts.add_argument('--string', '-s', dest='string_target', action='store_true',
- default=False,
- help='Treat TARGET as a string literal or String()')
+targ_opts.add_argument('--string', '-s', dest='string_targets',
+ action='append', default=[],
+ help='Add a string literal or String() to the list of targets')
### Output Options
out_opts = parser.add_argument_group('Output Options')
@@ -563,84 +562,89 @@ def find_roots_bfs(args, edges, graph, target):
########################################################
def target_edge(graph, target):
- targets = []
+ targets = set()
for origin, destinations in graph.edge_labels.items():
for destination in destinations:
if target in graph.edge_labels[origin][destination]:
- targets.append(destination)
- targets.append(origin)
+ targets.add(destination)
+ targets.add(origin)
sys.stderr.write('Found {} objects with edge label of {}\n'.format(len(targets), target))
return targets
def target_func(graph, target):
- targets = []
+ targets = set()
for addr, label in graph.node_labels.items():
if not label[:9] == 'Function ':
continue
if label[9:] == target:
- targets.append(addr)
+ targets.add(addr)
sys.stderr.write('Found {} functions named "{}"\n'.format(len(targets), target))
return targets
def target_gobject(graph, target):
- targets = []
+ targets = set()
for addr, label in graph.node_labels.items():
if label.endswith(target):
- targets.append(addr)
+ targets.add(addr)
sys.stderr.write('Found GObject with address of {}\n'.format(target))
return targets
def target_string(graph, target):
- targets = []
+ targets = set()
for addr, label in graph.node_labels.items():
if label[:7] == 'string ' and target in label[7:]:
- targets.append(addr)
+ targets.add(addr)
elif label[:10] == 'substring ' and target in label[10:]:
- targets.append(addr)
+ targets.add(addr)
sys.stderr.write('Found {} strings containing "{}"\n'.format(len(targets), target))
return targets
def target_type(graph, target):
- targets = []
+ targets = set()
for addr in edges.keys():
- if graph.node_labels.get(addr, '')[0:len(args.target)] == args.target:
- targets.append(addr)
+ if graph.node_labels.get(addr, '')[0:len(target)] == target:
+ targets.add(addr)
sys.stderr.write('Found {} targets with type "{}"\n'.format(len(targets), target))
return targets
def select_targets(args, edges, graph):
- if args.edge_target:
- return target_edge(graph, args.target)
- elif args.func_target:
- return target_func(graph, args.target)
- elif args.string_target:
- return target_string(graph, args.target)
- # If args.target seems like an address search for a JS Object, then GObject
- elif addr_regex.match(args.target):
- if args.target in edges:
- sys.stderr.write('Found object with address "{}"\n'.format(args.target))
- return [args.target]
+ targets = set()
+ for target in args.targets:
+ # If target seems like an address search for a JS Object, then GObject
+ if addr_regex.match(target):
+ if target in edges:
+ sys.stderr.write('Found object with address "{}"\n'.format(target))
+ targets.add(target)
+ else:
+ targets.update(target_gobject(graph, target))
else:
- return target_gobject(graph, args.target)
+ # Fallback to looking for JavaScript objects by class name
+ targets.update(target_type(graph, target))
+
+ for target in args.edge_targets:
+ targets.update(target_edge(graph, target))
+ for target in args.func_targets:
+ targets.update(target_func(graph, target))
+ for target in args.string_targets:
+ targets.update(target_string(graph, target))
- # Fallback to looking for JavaScript objects by class name
- return target_type(graph, args.target)
+ return list(targets)
if __name__ == "__main__":
@@ -655,8 +659,9 @@ if __name__ == "__main__":
args.hide_nodes.remove('GIRepositoryNamespace')
# Make sure we don't filter an explicit target
- if args.target in args.hide_nodes:
- args.hide_nodes.remove(args.target)
+ for target in args.targets:
+ if target in args.hide_nodes:
+ args.hide_nodes.remove(target)
# Heap diffing; we do these addrs separately due to the sheer amount
diff_addrs = []
@@ -669,7 +674,7 @@ if __name__ == "__main__":
targets = select_targets(args, edges, graph)
if len(targets) == 0:
- sys.stderr.write('No targets found for "{}".\n'.format(args.target))
+ sys.stderr.write('No targets found.\n')
sys.exit(-1)
elif args.count:
sys.exit(-1);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]