1*4882a593Smuzhiyun#!/usr/bin/env python 2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun# show_deltas: Read list of printk messages instrumented with 5*4882a593Smuzhiyun# time data, and format with time deltas. 6*4882a593Smuzhiyun# 7*4882a593Smuzhiyun# Also, you can show the times relative to a fixed point. 8*4882a593Smuzhiyun# 9*4882a593Smuzhiyun# Copyright 2003 Sony Corporation 10*4882a593Smuzhiyun# 11*4882a593Smuzhiyun 12*4882a593Smuzhiyunimport sys 13*4882a593Smuzhiyunimport string 14*4882a593Smuzhiyun 15*4882a593Smuzhiyundef usage(): 16*4882a593Smuzhiyun print ("""usage: show_delta [<options>] <filename> 17*4882a593Smuzhiyun 18*4882a593SmuzhiyunThis program parses the output from a set of printk message lines which 19*4882a593Smuzhiyunhave time data prefixed because the CONFIG_PRINTK_TIME option is set, or 20*4882a593Smuzhiyunthe kernel command line option "time" is specified. When run with no 21*4882a593Smuzhiyunoptions, the time information is converted to show the time delta between 22*4882a593Smuzhiyuneach printk line and the next. When run with the '-b' option, all times 23*4882a593Smuzhiyunare relative to a single (base) point in time. 24*4882a593Smuzhiyun 25*4882a593SmuzhiyunOptions: 26*4882a593Smuzhiyun -h Show this usage help. 27*4882a593Smuzhiyun -b <base> Specify a base for time references. 28*4882a593Smuzhiyun <base> can be a number or a string. 29*4882a593Smuzhiyun If it is a string, the first message line 30*4882a593Smuzhiyun which matches (at the beginning of the 31*4882a593Smuzhiyun line) is used as the time reference. 32*4882a593Smuzhiyun 33*4882a593Smuzhiyunex: $ dmesg >timefile 34*4882a593Smuzhiyun $ show_delta -b NET4 timefile 35*4882a593Smuzhiyun 36*4882a593Smuzhiyunwill show times relative to the line in the kernel output 37*4882a593Smuzhiyunstarting with "NET4". 38*4882a593Smuzhiyun""") 39*4882a593Smuzhiyun sys.exit(1) 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun# returns a tuple containing the seconds and text for each message line 42*4882a593Smuzhiyun# seconds is returned as a float 43*4882a593Smuzhiyun# raise an exception if no timing data was found 44*4882a593Smuzhiyundef get_time(line): 45*4882a593Smuzhiyun if line[0]!="[": 46*4882a593Smuzhiyun raise ValueError 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun # split on closing bracket 49*4882a593Smuzhiyun (time_str, rest) = string.split(line[1:],']',1) 50*4882a593Smuzhiyun time = string.atof(time_str) 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun #print "time=", time 53*4882a593Smuzhiyun return (time, rest) 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun# average line looks like: 57*4882a593Smuzhiyun# [ 0.084282] VFS: Mounted root (romfs filesystem) readonly 58*4882a593Smuzhiyun# time data is expressed in seconds.useconds, 59*4882a593Smuzhiyun# convert_line adds a delta for each line 60*4882a593Smuzhiyunlast_time = 0.0 61*4882a593Smuzhiyundef convert_line(line, base_time): 62*4882a593Smuzhiyun global last_time 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun try: 65*4882a593Smuzhiyun (time, rest) = get_time(line) 66*4882a593Smuzhiyun except: 67*4882a593Smuzhiyun # if any problem parsing time, don't convert anything 68*4882a593Smuzhiyun return line 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun if base_time: 71*4882a593Smuzhiyun # show time from base 72*4882a593Smuzhiyun delta = time - base_time 73*4882a593Smuzhiyun else: 74*4882a593Smuzhiyun # just show time from last line 75*4882a593Smuzhiyun delta = time - last_time 76*4882a593Smuzhiyun last_time = time 77*4882a593Smuzhiyun 78*4882a593Smuzhiyun return ("[%5.6f < %5.6f >]" % (time, delta)) + rest 79*4882a593Smuzhiyun 80*4882a593Smuzhiyundef main(): 81*4882a593Smuzhiyun base_str = "" 82*4882a593Smuzhiyun filein = "" 83*4882a593Smuzhiyun for arg in sys.argv[1:]: 84*4882a593Smuzhiyun if arg=="-b": 85*4882a593Smuzhiyun base_str = sys.argv[sys.argv.index("-b")+1] 86*4882a593Smuzhiyun elif arg=="-h": 87*4882a593Smuzhiyun usage() 88*4882a593Smuzhiyun else: 89*4882a593Smuzhiyun filein = arg 90*4882a593Smuzhiyun 91*4882a593Smuzhiyun if not filein: 92*4882a593Smuzhiyun usage() 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun try: 95*4882a593Smuzhiyun lines = open(filein,"r").readlines() 96*4882a593Smuzhiyun except: 97*4882a593Smuzhiyun print ("Problem opening file: %s" % filein) 98*4882a593Smuzhiyun sys.exit(1) 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun if base_str: 101*4882a593Smuzhiyun print ('base= "%s"' % base_str) 102*4882a593Smuzhiyun # assume a numeric base. If that fails, try searching 103*4882a593Smuzhiyun # for a matching line. 104*4882a593Smuzhiyun try: 105*4882a593Smuzhiyun base_time = float(base_str) 106*4882a593Smuzhiyun except: 107*4882a593Smuzhiyun # search for line matching <base> string 108*4882a593Smuzhiyun found = 0 109*4882a593Smuzhiyun for line in lines: 110*4882a593Smuzhiyun try: 111*4882a593Smuzhiyun (time, rest) = get_time(line) 112*4882a593Smuzhiyun except: 113*4882a593Smuzhiyun continue 114*4882a593Smuzhiyun if string.find(rest, base_str)==1: 115*4882a593Smuzhiyun base_time = time 116*4882a593Smuzhiyun found = 1 117*4882a593Smuzhiyun # stop at first match 118*4882a593Smuzhiyun break 119*4882a593Smuzhiyun if not found: 120*4882a593Smuzhiyun print ('Couldn\'t find line matching base pattern "%s"' % base_str) 121*4882a593Smuzhiyun sys.exit(1) 122*4882a593Smuzhiyun else: 123*4882a593Smuzhiyun base_time = 0.0 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun for line in lines: 126*4882a593Smuzhiyun print (convert_line(line, base_time),) 127*4882a593Smuzhiyun 128*4882a593Smuzhiyunmain() 129