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:
parent
d1abaeb3be
commit
1446794a89
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user