1*5e811a68SRob Bradford#!/bin/env python3 2*5e811a68SRob Bradford# 3*5e811a68SRob Bradford# Copyright © 2022 Intel Corporation 4*5e811a68SRob Bradford# 5*5e811a68SRob Bradford# SPDX-License-Identifier: Apache-2.0 6*5e811a68SRob Bradford# 7*5e811a68SRob Bradford 8*5e811a68SRob Bradfordfrom colorsys import hsv_to_rgb 9*5e811a68SRob Bradfordfrom random import random 10*5e811a68SRob Bradfordimport xml 11*5e811a68SRob Bradfordimport json 12*5e811a68SRob Bradfordfrom sys import argv, stderr 13*5e811a68SRob Bradfordimport xml.etree.ElementTree as ET 14*5e811a68SRob Bradford 15*5e811a68SRob Bradfordwidth = 1000 16*5e811a68SRob Bradfordheight = 200 17*5e811a68SRob Bradfordpadding = 10 18*5e811a68SRob Bradford 19*5e811a68SRob Bradfordif len(argv) < 3: 20*5e811a68SRob Bradford stderr.write("./ch-trace-visualiser <trace file> <output file>\n") 21*5e811a68SRob Bradford exit(1) 22*5e811a68SRob Bradford 23*5e811a68SRob Bradford 24*5e811a68SRob Bradforddef nano_time(duration): 25*5e811a68SRob Bradford return (duration["secs"] * 10 ** 9) + duration["nanos"] 26*5e811a68SRob Bradford 27*5e811a68SRob Bradford 28*5e811a68SRob Bradforddef duration_to_px_x(start): 29*5e811a68SRob Bradford return (nano_time(start) * (width - 2 * padding)) / total_time 30*5e811a68SRob Bradford 31*5e811a68SRob Bradford 32*5e811a68SRob Bradforddef duration_to_px_width(start, end): 33*5e811a68SRob Bradford return ((nano_time(end) - nano_time(start)) * (width - 2 * padding)) / total_time 34*5e811a68SRob Bradford 35*5e811a68SRob Bradford 36*5e811a68SRob Bradforddef duration_ms(start, end): 37*5e811a68SRob Bradford return (nano_time(end) - nano_time(start)) // 1000000 38*5e811a68SRob Bradford 39*5e811a68SRob Bradford 40*5e811a68SRob Bradfordf = open(argv[1]) 41*5e811a68SRob Bradfordreport = json.load(f) 42*5e811a68SRob Bradfordtotal_time = nano_time(report["duration"]) 43*5e811a68SRob Bradford 44*5e811a68SRob Bradfordsvg = ET.Element("svg", attrib={"width": str(width), "height": str(height), 45*5e811a68SRob Bradford "xmlns": "http://www.w3.org/2000/svg", 46*5e811a68SRob Bradford "xmlns:svg": "http://www.w3.org/2000/svg" 47*5e811a68SRob Bradford }) 48*5e811a68SRob Bradford 49*5e811a68SRob Bradford 50*5e811a68SRob Bradforddef add_traced_block(thread_group, depth, traced_block): 51*5e811a68SRob Bradford g = ET.SubElement(thread_group, "g", 52*5e811a68SRob Bradford attrib={"transform": "translate(%d,%d)" % ( 53*5e811a68SRob Bradford duration_to_px_x(traced_block["timestamp"]), 54*5e811a68SRob Bradford (depth * 18))}) 55*5e811a68SRob Bradford width = str(duration_to_px_width( 56*5e811a68SRob Bradford traced_block["timestamp"], traced_block["end_timestamp"])) 57*5e811a68SRob Bradford 58*5e811a68SRob Bradford clip = ET.SubElement(g, "clipPath", attrib={ 59*5e811a68SRob Bradford "id": "clip_%s" % (traced_block["event"]), 60*5e811a68SRob Bradford }) 61*5e811a68SRob Bradford ET.SubElement(clip, "rect", attrib={ 62*5e811a68SRob Bradford "width": width, 63*5e811a68SRob Bradford "height": "1.5em", 64*5e811a68SRob Bradford "x": "0", 65*5e811a68SRob Bradford "y": "0" 66*5e811a68SRob Bradford }) 67*5e811a68SRob Bradford 68*5e811a68SRob Bradford (red, green, blue) = hsv_to_rgb(random(), 0.3, 0.75) 69*5e811a68SRob Bradford ET.SubElement(g, "rect", attrib={ 70*5e811a68SRob Bradford "width": width, 71*5e811a68SRob Bradford "height": "1.5em", 72*5e811a68SRob Bradford "fill": "#%x%x%x" % (int(red * 255), int(green * 255), int(blue * 255)) 73*5e811a68SRob Bradford }) 74*5e811a68SRob Bradford text = ET.SubElement(g, "text", attrib={ 75*5e811a68SRob Bradford "x": "0.2em", "y": "1em", "clip-path": "url(#clip_%s)" % (traced_block["event"])}) 76*5e811a68SRob Bradford text.text = "%s (%dms)" % (traced_block["event"], duration_ms( 77*5e811a68SRob Bradford traced_block["timestamp"], traced_block["end_timestamp"])) 78*5e811a68SRob Bradford 79*5e811a68SRob Bradford 80*5e811a68SRob Bradfordthread_size = (height - (2 * padding)) / len(report["events"]) 81*5e811a68SRob Bradfordthread_offset = padding 82*5e811a68SRob Bradford 83*5e811a68SRob Bradfordfor thread in report["events"]: 84*5e811a68SRob Bradford thread_events = report["events"][thread] 85*5e811a68SRob Bradford thread_events = sorted( 86*5e811a68SRob Bradford thread_events, key=lambda traced_block: nano_time(traced_block["timestamp"])) 87*5e811a68SRob Bradford thread_group = ET.SubElement( 88*5e811a68SRob Bradford svg, "g", attrib={"transform": "translate(%d,%d)" % (padding, thread_offset)}) 89*5e811a68SRob Bradford thread_text = ET.SubElement(thread_group, "text", attrib={ 90*5e811a68SRob Bradford "y": "1em"}).text = "Thread: %s" % (thread) 91*5e811a68SRob Bradford thread_children = ET.SubElement(thread_group, "g", attrib={ 92*5e811a68SRob Bradford "transform": "translate(0, 18)"}) 93*5e811a68SRob Bradford for traced_block in thread_events: 94*5e811a68SRob Bradford add_traced_block(thread_children, traced_block["depth"], traced_block) 95*5e811a68SRob Bradford thread_offset += thread_size + padding 96*5e811a68SRob Bradford 97*5e811a68SRob Bradfordxml = ET.ElementTree(element=svg) 98*5e811a68SRob Bradfordxml.write(argv[2], xml_declaration=True) 99