Commit 1446794a authored by Todd Brandt's avatar Todd Brandt Committed by Rafael J. Wysocki
Browse files

pm-graph v5.5



Upgrade bootgraph/sleepgraph to be able to run on python2 and python3.
Both now simply require python, the system can choose which to use.

bootgraph python3 update:
- add floor function to handle integer arithmetic
- change argument loop to use next() instead of args.next()
- open dmesg log and popen in binary, use decode(ascii, ignore)
- sort all html data to allow diff between python versions
- change exception handler to use python3 as instead of comma

sleepgraph python3 update:
- import configparser not ConfigParser (p2 needs python-configparser)
- add floor function to handle integer arithmetic
- change argument loop to use next() instead of args.next()
- handle popen output in binary, use decode(ascii, ignore)
- sort all html/output data to allow diff between python versions
- force gzip open to use text mode, same for file open
- ensure no binary data is written to logs (ascii convert devprops info)
- use codecs library to handle zlib encoding for mcelog data
- remove all uses of python3.7 keyword "async" as members or vars
- assume all FPDT and DMI data is in binary string form

sleepgraph:
- turbostat will be used by default if it's found & the mode is freeze
- a new option "-noturbostat" will disable its use
- fix bug where two callgraphs with the same start time overwrite.
- fix s2idle processing where two suspend/resume_machines occur back2back
- update getexec function to use which first (assuming PATH exists)
- new platforminfo data in log with: lspci, gpe counts, /proc/interrupts
- new data is zipped, b64 encoded, and tacked on the end of ftrace

Signed-off-by: default avatarTodd Brandt <todd.e.brandt@linux.intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent d1abaeb3
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
                     p m - g r a p h

   pm-graph: suspend/resume/boot timing analysis tools
    Version: 5.4
    Version: 5.5
     Author: Todd Brandt <todd.e.brandt@intel.com>
  Home Page: https://01.org/pm-graph

@@ -18,6 +18,10 @@
	- upstream version in git:
	  https://github.com/intel/pm-graph/

 Requirements:
	- runs with python2 or python3, choice is made by /usr/bin/python link
	- python2 now requires python-configparser be installed

 Table of Contents
	- Overview
	- Setup
+40 −19
Original line number Diff line number Diff line
#!/usr/bin/python2
#!/usr/bin/python
# SPDX-License-Identifier: GPL-2.0-only
#
# Tool for analyzing boot timing
# Copyright (c) 2013, Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
# more details.
#
# Authors:
#	 Todd Brandt <todd.e.brandt@linux.intel.com>
#
@@ -81,7 +90,7 @@ class SystemValues(aslib.SystemValues):
		cmdline = 'initcall_debug log_buf_len=32M'
		if self.useftrace:
			if self.cpucount > 0:
				bs = min(self.memtotal / 2, 2*1024*1024) / self.cpucount
				bs = min(self.memtotal // 2, 2*1024*1024) // self.cpucount
			else:
				bs = 131072
			cmdline += ' trace_buf_size=%dK trace_clock=global '\
@@ -137,13 +146,13 @@ class SystemValues(aslib.SystemValues):
			if arg in ['-h', '-v', '-cronjob', '-reboot', '-verbose']:
				continue
			elif arg in ['-o', '-dmesg', '-ftrace', '-func']:
				args.next()
				next(args)
				continue
			elif arg == '-result':
				cmdline += ' %s "%s"' % (arg, os.path.abspath(args.next()))
				cmdline += ' %s "%s"' % (arg, os.path.abspath(next(args)))
				continue
			elif arg == '-cgskip':
				file = self.configFile(args.next())
				file = self.configFile(next(args))
				cmdline += ' %s "%s"' % (arg, os.path.abspath(file))
				continue
			cmdline += ' '+arg
@@ -292,11 +301,11 @@ def parseKernelLog():
	tp = aslib.TestProps()
	devtemp = dict()
	if(sysvals.dmesgfile):
		lf = open(sysvals.dmesgfile, 'r')
		lf = open(sysvals.dmesgfile, 'rb')
	else:
		lf = Popen('dmesg', stdout=PIPE).stdout
	for line in lf:
		line = line.replace('\r\n', '')
		line = aslib.ascii(line).replace('\r\n', '')
		# grab the stamp and sysinfo
		if re.match(tp.stampfmt, line):
			tp.stamp = line
@@ -649,7 +658,7 @@ def createBootGraph(data):
		statinfo += '\t"%s": [\n\t\t"%s",\n' % (n, devstats[n]['info'])
		if 'fstat' in devstats[n]:
			funcs = devstats[n]['fstat']
			for f in sorted(funcs, key=funcs.get, reverse=True):
			for f in sorted(funcs, key=lambda k:(funcs[k], k), reverse=True):
				if funcs[f][0] < 0.01 and len(funcs) > 10:
					break
				statinfo += '\t\t"%f|%s|%d",\n' % (funcs[f][0], f, funcs[f][1])
@@ -729,7 +738,7 @@ def updateCron(restore=False):
		op.write('@reboot python %s\n' % sysvals.cronjobCmdString())
		op.close()
		res = call([cmd, cronfile])
	except Exception, e:
	except Exception as e:
		pprint('Exception: %s' % str(e))
		shutil.move(backfile, cronfile)
		res = -1
@@ -745,7 +754,7 @@ def updateGrub(restore=False):
		try:
			call(sysvals.blexec, stderr=PIPE, stdout=PIPE,
				env={'PATH': '.:/sbin:/usr/sbin:/usr/bin:/sbin:/bin'})
		except Exception, e:
		except Exception as e:
			pprint('Exception: %s\n' % str(e))
		return
	# extract the option and create a grub config without it
@@ -792,7 +801,7 @@ def updateGrub(restore=False):
		op.close()
		res = call(sysvals.blexec)
		os.remove(grubfile)
	except Exception, e:
	except Exception as e:
		pprint('Exception: %s' % str(e))
		res = -1
	# cleanup
@@ -866,6 +875,7 @@ def printHelp():
	'Other commands:\n'\
	'  -flistall     Print all functions capable of being captured in ftrace\n'\
	'  -sysinfo      Print out system info extracted from BIOS\n'\
	'  -which exec   Print an executable path, should function even without PATH\n'\
	' [redo]\n'\
	'  -dmesg file   Create HTML output using dmesg input (used with -ftrace)\n'\
	'  -ftrace file  Create HTML output using ftrace input (used with -dmesg)\n'\
@@ -907,13 +917,13 @@ if __name__ == '__main__':
			sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0)
		elif(arg == '-cgfilter'):
			try:
				val = args.next()
				val = next(args)
			except:
				doError('No callgraph functions supplied', True)
			sysvals.setCallgraphFilter(val)
		elif(arg == '-cgskip'):
			try:
				val = args.next()
				val = next(args)
			except:
				doError('No file supplied', True)
			if val.lower() in switchoff:
@@ -924,7 +934,7 @@ if __name__ == '__main__':
					doError('%s does not exist' % cgskip)
		elif(arg == '-bl'):
			try:
				val = args.next()
				val = next(args)
			except:
				doError('No boot loader name supplied', True)
			if val.lower() not in ['grub']:
@@ -937,7 +947,7 @@ if __name__ == '__main__':
			sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000)
		elif(arg == '-func'):
			try:
				val = args.next()
				val = next(args)
			except:
				doError('No filter functions supplied', True)
			sysvals.useftrace = True
@@ -946,7 +956,7 @@ if __name__ == '__main__':
			sysvals.setGraphFilter(val)
		elif(arg == '-ftrace'):
			try:
				val = args.next()
				val = next(args)
			except:
				doError('No ftrace file supplied', True)
			if(os.path.exists(val) == False):
@@ -959,7 +969,7 @@ if __name__ == '__main__':
			sysvals.cgexp = True
		elif(arg == '-dmesg'):
			try:
				val = args.next()
				val = next(args)
			except:
				doError('No dmesg file supplied', True)
			if(os.path.exists(val) == False):
@@ -968,13 +978,13 @@ if __name__ == '__main__':
			sysvals.dmesgfile = val
		elif(arg == '-o'):
			try:
				val = args.next()
				val = next(args)
			except:
				doError('No subdirectory name supplied', True)
			sysvals.testdir = sysvals.setOutputFolder(val)
		elif(arg == '-result'):
			try:
				val = args.next()
				val = next(args)
			except:
				doError('No result file supplied', True)
			sysvals.result = val
@@ -986,6 +996,17 @@ if __name__ == '__main__':
		# remaining options are only for cron job use
		elif(arg == '-cronjob'):
			sysvals.iscronjob = True
		elif(arg == '-which'):
			try:
				val = next(args)
			except:
				doError('No executable supplied', True)
			out = sysvals.getExec(val)
			if not out:
				print('%s not found' % val)
				sys.exit(1)
			print(out)
			sys.exit(0)
		else:
			doError('Invalid argument: '+arg, True)

+4 −4
Original line number Diff line number Diff line
@@ -53,10 +53,10 @@ disable rtcwake and require a user keypress to resume.
Add the dmesg and ftrace logs to the html output. They will be viewable by
clicking buttons in the timeline.
.TP
\fB-turbostat\fR
Use turbostat to execute the command in freeze mode (default: disabled). This
will provide turbostat output in the log which will tell you which actual
power modes were entered.
\fB-noturbostat\fR
By default, if turbostat is found and the requested mode is freeze, sleepgraph
will execute the suspend via turbostat and collect data in the timeline log.
This option disables the use of turbostat.
.TP
\fB-result \fIfile\fR
Export a results table to a text file for parsing.
+338 −272

File changed.

Preview size limit exceeded, changes collapsed.