History

scripts/timers: Add timer_migration_tree.py

Introduce a script that provides a simple ascii representation of the timer migration tree on top of boot trace events. First boot with: trace_event==tmigr_connect_cpu_parent,tmigr_connect_child_parent Then parse the result with: scripts/timer_migration_tree.py < /sys/kernel/tracing/trace On a system with 8 CPUs, this produces the following output: Tree for capacity 1024 /-0, node 0, lvl:-1 | |--1, node 0, lvl:-1 | |--2, node 0, lvl:-1 | |--3, node 0, lvl:-1 -- /00000000dcebac8b, node 0, lvl:0 |--4, node 0, lvl:-1 | |--5, node 0, lvl:-1 | |--6, node 0, lvl:-1 | \-7, node 0, lvl:-1

Frederic Weisbecker committed 6 months ago

Commit cab0cd01 parent 5a7dfbc1 file · +122 −0Browse files

Unified · Split

scripts/timer_migration_tree.py+122−0
@@ -0,0 +1,122 @@
1+#!/usr/bin/env python3
2+# SPDX-License-Identifier: GPL-2.0
3+
4+"""
5+Draw the timer migration tree.
6+
7+1) Boot with trace_event==tmigr_connect_cpu_parent,tmigr_connect_child_parent
8+2) ./timer_migration_tree.py < /sys/kernel/tracing/trace
9+"""
10+
11+import re, sys
12+from ete3 import Tree
13+
14+class Node:
15+ def __init__(self, group):
16+ self.group = group
17+ self.children = []
18+ self.parent = None
19+ self.num_children = 0
20+ self.groupmask = 0
21+ self.lvl = -1
22+
23+ def set_groupmask(self, groupmask):
24+ self.groupmask = groupmask
25+
26+ def set_parent(self, parent):
27+ self.parent = parent
28+
29+ def add_child(self, child):
30+ self.children.append(child)
31+
32+ def set_lvl(self, lvl):
33+ self.lvl = lvl
34+
35+ def set_numa(self, numa):
36+ self.numa = numa
37+
38+ def set_num_children(self, num_children):
39+ self.num_children = num_children
40+
41+ def __repr__(self):
42+ if self.parent:
43+ parent_grp = self.parent.group
44+ else:
45+ parent_grp = "-"
46+ return "Group: %s mask: %s parent: %s lvl: %d numa: %d num_children: %d" % (self.group, self.groupmask, parent_grp, self.lvl, self.numa, self.num_children)
47+
48+hierarchies = { }
49+
50+def get_hierarchy(capacity):
51+ if capacity not in hierarchies:
52+ hierarchies[capacity] = {}
53+ return hierarchies[capacity]
54+
55+def get_node(capacity, group):
56+ hier = get_hierarchy(capacity)
57+ if group in hier:
58+ return hier[group]
59+ else:
60+ n = Node(group)
61+ hier[group] = n
62+ return n
63+
64+def tmigr_connect_cpu_parent(ts, line):
65+ s = re.search("tmigr_connect_cpu_parent: cpu=([0-9]+) groupmask=([0-9a-zA-Z]+) parent=([0-9a-zA-Z]+) lvl=([0-9]+) numa=([-]?[0-9]+) capacity=([-]?[0-9]+) num_children=([0-9]+)", line)
66+ if s is None:
67+ return False
68+ (cpu, groupmask, parent, lvl, numa, capacity, num_children) = (int(s.group(1)), s.group(2), s.group(3), int(s.group(4)), int(s.group(5)), int(s.group(6)), int(s.group(7)))
69+ n = get_node(capacity, cpu)
70+ p = get_node(capacity, parent)
71+ n.set_parent(p)
72+ n.set_groupmask(groupmask)
73+ n.set_lvl(-1)
74+ p.set_lvl(lvl)
75+ p.set_numa(numa)
76+ n.set_numa(numa)
77+ p.set_num_children(num_children)
78+ p.add_child(n)
79+
80+def tmigr_connect_child_parent(ts, line):
81+ s = re.search("tmigr_connect_child_parent: group=([0-9a-zA-Z]+) groupmask=([0-9a-zA-Z]+) parent=([0-9a-zA-Z]+) lvl=([0-9]+) numa=([-]?[0-9]+) capacity=([-]?[0-9]+) num_children=([0-9]+)", line)
82+ if s is None:
83+ return False
84+ (group, groupmask, parent, lvl, numa, capacity, num_children) = (s.group(1), s.group(2), s.group(3), int(s.group(4)), int(s.group(5)), int(s.group(6)), int(s.group(7)))
85+ n = get_node(capacity, group)
86+ p = get_node(capacity, parent)
87+ n.set_parent(p)
88+ n.set_groupmask(groupmask)
89+ p.set_lvl(lvl)
90+ p.set_numa(numa)
91+ p.set_num_children(num_children)
92+ p.add_child(n)
93+
94+def populate(enode, node):
95+ enode = enode.add_child(name = node.group)
96+ enode.add_feature("groupmask", "m:%s" % node.groupmask)
97+ enode.add_feature("lvl", "lvl:%d" % node.lvl)
98+ enode.add_feature("numa", "node %d" % node.numa)
99+ enode.add_feature("num_children", "c=%d" % node.num_children)
100+ for child in node.children:
101+ populate(enode, child)
102+
103+if __name__ == "__main__":
104+ for line in sys.stdin:
105+ s = re.search("([0-9]+[.][0-9]{6}): (.+?)$", line, re.S)
106+ if s is not None:
107+ if tmigr_connect_cpu_parent(float(s.group(1)), s.group(2)):
108+ continue
109+ if tmigr_connect_child_parent(float(s.group(1)), s.group(2)):
110+ continue
111+
112+ for cap in hierarchies:
113+ h = hierarchies[cap]
114+ print("Tree for capacity %d" % cap)
115+ for k in h:
116+ n = h[k]
117+ while n.parent != None:
118+ n = n.parent
119+ root = Tree()
120+ populate(root, n)
121+ print(root.get_ascii(show_internal=True, attributes=["name", "numa", "lvl"]))
122+ break

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t