xref: /OK3568_Linux_fs/kernel/scripts/show_delta (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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