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