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: Todd Brandt <todd.e.brandt@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Todd Brandt 2019-08-12 14:08:44 -07:00 committed by Rafael J. Wysocki
parent d1abaeb3be
commit 1446794a89
4 changed files with 387 additions and 296 deletions

View File

@ -1,7 +1,7 @@
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

View File

@ -1,9 +1,18 @@
#!/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)

View File

@ -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.

File diff suppressed because it is too large Load Diff