aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/graphstats.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/graphstats.py')
-rwxr-xr-xscripts/graphstats.py299
1 files changed, 172 insertions, 127 deletions
diff --git a/scripts/graphstats.py b/scripts/graphstats.py
index 5cd2ad34..4a8a7164 100755
--- a/scripts/graphstats.py
+++ b/scripts/graphstats.py
@@ -7,88 +7,107 @@
import optparse, datetime
import matplotlib
-MAXBANDWIDTH=25000.
-MAXBUFFER=2.
-STATS_INTERVAL=5.
-TASK_MAX=0.0025
+MAXBANDWIDTH = 25000.0
+MAXBUFFER = 2.0
+STATS_INTERVAL = 5.0
+TASK_MAX = 0.0025
APPLY_PREFIX = [
- 'mcu_awake', 'mcu_task_avg', 'mcu_task_stddev', 'bytes_write',
- 'bytes_read', 'bytes_retransmit', 'freq', 'adj',
- 'target', 'temp', 'pwm'
+ "mcu_awake",
+ "mcu_task_avg",
+ "mcu_task_stddev",
+ "bytes_write",
+ "bytes_read",
+ "bytes_retransmit",
+ "freq",
+ "adj",
+ "target",
+ "temp",
+ "pwm",
]
+
def parse_log(logname, mcu):
if mcu is None:
mcu = "mcu"
mcu_prefix = mcu + ":"
- apply_prefix = { p: 1 for p in APPLY_PREFIX }
- f = open(logname, 'r')
+ apply_prefix = {p: 1 for p in APPLY_PREFIX}
+ f = open(logname, "r")
out = []
for line in f:
parts = line.split()
- if not parts or parts[0] not in ('Stats', 'INFO:root:Stats'):
- #if parts and parts[0] == 'INFO:root:shutdown:':
+ if not parts or parts[0] not in ("Stats", "INFO:root:Stats"):
+ # if parts and parts[0] == 'INFO:root:shutdown:':
# break
continue
prefix = ""
keyparts = {}
for p in parts[2:]:
- if '=' not in p:
+ if "=" not in p:
prefix = p
if prefix == mcu_prefix:
- prefix = ''
+ prefix = ""
continue
- name, val = p.split('=', 1)
+ name, val = p.split("=", 1)
if name in apply_prefix:
name = prefix + name
keyparts[name] = val
- if 'print_time' not in keyparts:
+ if "print_time" not in keyparts:
continue
- keyparts['#sampletime'] = float(parts[1][:-1])
+ keyparts["#sampletime"] = float(parts[1][:-1])
out.append(keyparts)
f.close()
return out
+
def setup_matplotlib(output_to_file):
global matplotlib
if output_to_file:
- matplotlib.use('Agg')
+ matplotlib.use("Agg")
import matplotlib.pyplot, matplotlib.dates, matplotlib.font_manager
import matplotlib.ticker
+
def find_print_restarts(data):
runoff_samples = {}
- last_runoff_start = last_buffer_time = last_sampletime = 0.
+ last_runoff_start = last_buffer_time = last_sampletime = 0.0
last_print_stall = 0
for d in reversed(data):
# Check for buffer runoff
- sampletime = d['#sampletime']
- buffer_time = float(d.get('buffer_time', 0.))
- if (last_runoff_start and last_sampletime - sampletime < 5
- and buffer_time > last_buffer_time):
+ sampletime = d["#sampletime"]
+ buffer_time = float(d.get("buffer_time", 0.0))
+ if (
+ last_runoff_start
+ and last_sampletime - sampletime < 5
+ and buffer_time > last_buffer_time
+ ):
runoff_samples[last_runoff_start][1].append(sampletime)
- elif buffer_time < 1.:
+ elif buffer_time < 1.0:
last_runoff_start = sampletime
runoff_samples[last_runoff_start] = [False, [sampletime]]
else:
- last_runoff_start = 0.
+ last_runoff_start = 0.0
last_buffer_time = buffer_time
last_sampletime = sampletime
# Check for print stall
- print_stall = int(d['print_stall'])
+ print_stall = int(d["print_stall"])
if print_stall < last_print_stall:
if last_runoff_start:
runoff_samples[last_runoff_start][0] = True
last_print_stall = print_stall
- sample_resets = {sampletime: 1 for stall, samples in runoff_samples.values()
- for sampletime in samples if not stall}
+ sample_resets = {
+ sampletime: 1
+ for stall, samples in runoff_samples.values()
+ for sampletime in samples
+ if not stall
+ }
return sample_resets
+
def plot_mcu(data, maxbw):
# Generate data for plot
- basetime = lasttime = data[0]['#sampletime']
- lastbw = float(data[0]['bytes_write']) + float(data[0]['bytes_retransmit'])
+ basetime = lasttime = data[0]["#sampletime"]
+ lastbw = float(data[0]["bytes_write"]) + float(data[0]["bytes_retransmit"])
sample_resets = find_print_restarts(data)
times = []
bwdeltas = []
@@ -96,165 +115,171 @@ def plot_mcu(data, maxbw):
awake = []
hostbuffers = []
for d in data:
- st = d['#sampletime']
+ st = d["#sampletime"]
timedelta = st - lasttime
- if timedelta <= 0.:
+ if timedelta <= 0.0:
continue
- bw = float(d['bytes_write']) + float(d['bytes_retransmit'])
+ bw = float(d["bytes_write"]) + float(d["bytes_retransmit"])
if bw < lastbw:
lastbw = bw
continue
- load = float(d['mcu_task_avg']) + 3*float(d['mcu_task_stddev'])
- if st - basetime < 15.:
- load = 0.
- pt = float(d['print_time'])
- hb = float(d['buffer_time'])
+ load = float(d["mcu_task_avg"]) + 3 * float(d["mcu_task_stddev"])
+ if st - basetime < 15.0:
+ load = 0.0
+ pt = float(d["print_time"])
+ hb = float(d["buffer_time"])
if hb >= MAXBUFFER or st in sample_resets:
- hb = 0.
+ hb = 0.0
else:
- hb = 100. * (MAXBUFFER - hb) / MAXBUFFER
+ hb = 100.0 * (MAXBUFFER - hb) / MAXBUFFER
hostbuffers.append(hb)
times.append(datetime.datetime.utcfromtimestamp(st))
- bwdeltas.append(100. * (bw - lastbw) / (maxbw * timedelta))
- loads.append(100. * load / TASK_MAX)
- awake.append(100. * float(d.get('mcu_awake', 0.)) / STATS_INTERVAL)
+ bwdeltas.append(100.0 * (bw - lastbw) / (maxbw * timedelta))
+ loads.append(100.0 * load / TASK_MAX)
+ awake.append(100.0 * float(d.get("mcu_awake", 0.0)) / STATS_INTERVAL)
lasttime = st
lastbw = bw
# Build plot
fig, ax1 = matplotlib.pyplot.subplots()
ax1.set_title("MCU bandwidth and load utilization")
- ax1.set_xlabel('Time')
- ax1.set_ylabel('Usage (%)')
- ax1.plot_date(times, bwdeltas, 'g', label='Bandwidth', alpha=0.8)
- ax1.plot_date(times, loads, 'r', label='MCU load', alpha=0.8)
- ax1.plot_date(times, hostbuffers, 'c', label='Host buffer', alpha=0.8)
- ax1.plot_date(times, awake, 'y', label='Awake time', alpha=0.6)
+ ax1.set_xlabel("Time")
+ ax1.set_ylabel("Usage (%)")
+ ax1.plot_date(times, bwdeltas, "g", label="Bandwidth", alpha=0.8)
+ ax1.plot_date(times, loads, "r", label="MCU load", alpha=0.8)
+ ax1.plot_date(times, hostbuffers, "c", label="Host buffer", alpha=0.8)
+ ax1.plot_date(times, awake, "y", label="Awake time", alpha=0.6)
fontP = matplotlib.font_manager.FontProperties()
- fontP.set_size('x-small')
- ax1.legend(loc='best', prop=fontP)
- ax1.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%H:%M'))
+ fontP.set_size("x-small")
+ ax1.legend(loc="best", prop=fontP)
+ ax1.xaxis.set_major_formatter(matplotlib.dates.DateFormatter("%H:%M"))
ax1.grid(True)
return fig
+
def plot_system(data):
# Generate data for plot
- lasttime = data[0]['#sampletime']
- lastcputime = float(data[0]['cputime'])
+ lasttime = data[0]["#sampletime"]
+ lastcputime = float(data[0]["cputime"])
times = []
sysloads = []
cputimes = []
memavails = []
for d in data:
- st = d['#sampletime']
+ st = d["#sampletime"]
timedelta = st - lasttime
- if timedelta <= 0.:
+ if timedelta <= 0.0:
continue
lasttime = st
times.append(datetime.datetime.utcfromtimestamp(st))
- cputime = float(d['cputime'])
- cpudelta = max(0., min(1.5, (cputime - lastcputime) / timedelta))
+ cputime = float(d["cputime"])
+ cpudelta = max(0.0, min(1.5, (cputime - lastcputime) / timedelta))
lastcputime = cputime
- cputimes.append(cpudelta * 100.)
- sysloads.append(float(d['sysload']) * 100.)
- memavails.append(float(d['memavail']))
+ cputimes.append(cpudelta * 100.0)
+ sysloads.append(float(d["sysload"]) * 100.0)
+ memavails.append(float(d["memavail"]))
# Build plot
fig, ax1 = matplotlib.pyplot.subplots()
ax1.set_title("System load utilization")
- ax1.set_xlabel('Time')
- ax1.set_ylabel('Load (% of a core)')
- ax1.plot_date(times, sysloads, '-', label='system load',
- color='cyan', alpha=0.8)
- ax1.plot_date(times, cputimes, '-', label='process time',
- color='red', alpha=0.8)
+ ax1.set_xlabel("Time")
+ ax1.set_ylabel("Load (% of a core)")
+ ax1.plot_date(times, sysloads, "-", label="system load", color="cyan", alpha=0.8)
+ ax1.plot_date(times, cputimes, "-", label="process time", color="red", alpha=0.8)
ax2 = ax1.twinx()
- ax2.set_ylabel('Available memory (KB)')
- ax2.plot_date(times, memavails, '-', label='system memory',
- color='yellow', alpha=0.3)
+ ax2.set_ylabel("Available memory (KB)")
+ ax2.plot_date(
+ times, memavails, "-", label="system memory", color="yellow", alpha=0.3
+ )
fontP = matplotlib.font_manager.FontProperties()
- fontP.set_size('x-small')
+ fontP.set_size("x-small")
ax1li, ax1la = ax1.get_legend_handles_labels()
ax2li, ax2la = ax2.get_legend_handles_labels()
- ax1.legend(ax1li + ax2li, ax1la + ax2la, loc='best', prop=fontP)
- ax1.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%H:%M'))
+ ax1.legend(ax1li + ax2li, ax1la + ax2la, loc="best", prop=fontP)
+ ax1.xaxis.set_major_formatter(matplotlib.dates.DateFormatter("%H:%M"))
ax1.grid(True)
return fig
+
def plot_mcu_frequencies(data):
all_keys = {}
for d in data:
all_keys.update(d)
- graph_keys = { key: ([], []) for key in all_keys
- if (key in ("freq", "adj")
- or (key.endswith(":freq") or key.endswith(":adj"))) }
+ graph_keys = {
+ key: ([], [])
+ for key in all_keys
+ if (key in ("freq", "adj") or (key.endswith(":freq") or key.endswith(":adj")))
+ }
for d in data:
- st = datetime.datetime.utcfromtimestamp(d['#sampletime'])
+ st = datetime.datetime.utcfromtimestamp(d["#sampletime"])
for key, (times, values) in graph_keys.items():
val = d.get(key)
- if val not in (None, '0', '1'):
+ if val not in (None, "0", "1"):
times.append(st)
values.append(float(val))
- est_mhz = { key: round((sum(values)/len(values)) / 1000000.)
- for key, (times, values) in graph_keys.items() }
+ est_mhz = {
+ key: round((sum(values) / len(values)) / 1000000.0)
+ for key, (times, values) in graph_keys.items()
+ }
# Build plot
fig, ax1 = matplotlib.pyplot.subplots()
ax1.set_title("MCU frequencies")
- ax1.set_xlabel('Time')
- ax1.set_ylabel('Microsecond deviation')
+ ax1.set_xlabel("Time")
+ ax1.set_ylabel("Microsecond deviation")
for key in sorted(graph_keys):
times, values = graph_keys[key]
mhz = est_mhz[key]
label = "%s(%dMhz)" % (key, mhz)
- hz = mhz * 1000000.
- ax1.plot_date(times, [(v - hz)/mhz for v in values], '.', label=label)
+ hz = mhz * 1000000.0
+ ax1.plot_date(times, [(v - hz) / mhz for v in values], ".", label=label)
fontP = matplotlib.font_manager.FontProperties()
- fontP.set_size('x-small')
- ax1.legend(loc='best', prop=fontP)
- ax1.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%H:%M'))
- ax1.yaxis.set_major_formatter(matplotlib.ticker.FormatStrFormatter('%d'))
+ fontP.set_size("x-small")
+ ax1.legend(loc="best", prop=fontP)
+ ax1.xaxis.set_major_formatter(matplotlib.dates.DateFormatter("%H:%M"))
+ ax1.yaxis.set_major_formatter(matplotlib.ticker.FormatStrFormatter("%d"))
ax1.grid(True)
return fig
+
def plot_mcu_frequency(data, mcu):
all_keys = {}
for d in data:
all_keys.update(d)
- graph_keys = { key: ([], []) for key in all_keys
- if key in ("freq", "adj") }
+ graph_keys = {key: ([], []) for key in all_keys if key in ("freq", "adj")}
for d in data:
- st = datetime.datetime.utcfromtimestamp(d['#sampletime'])
+ st = datetime.datetime.utcfromtimestamp(d["#sampletime"])
for key, (times, values) in graph_keys.items():
val = d.get(key)
- if val not in (None, '0', '1'):
+ if val not in (None, "0", "1"):
times.append(st)
values.append(float(val))
# Build plot
fig, ax1 = matplotlib.pyplot.subplots()
ax1.set_title("MCU '%s' frequency" % (mcu,))
- ax1.set_xlabel('Time')
- ax1.set_ylabel('Frequency')
+ ax1.set_xlabel("Time")
+ ax1.set_ylabel("Frequency")
for key in sorted(graph_keys):
times, values = graph_keys[key]
- ax1.plot_date(times, values, '.', label=key)
+ ax1.plot_date(times, values, ".", label=key)
fontP = matplotlib.font_manager.FontProperties()
- fontP.set_size('x-small')
- ax1.legend(loc='best', prop=fontP)
- ax1.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%H:%M'))
- ax1.yaxis.set_major_formatter(matplotlib.ticker.FormatStrFormatter('%d'))
+ fontP.set_size("x-small")
+ ax1.legend(loc="best", prop=fontP)
+ ax1.xaxis.set_major_formatter(matplotlib.dates.DateFormatter("%H:%M"))
+ ax1.yaxis.set_major_formatter(matplotlib.ticker.FormatStrFormatter("%d"))
ax1.grid(True)
return fig
+
def plot_temperature(data, heaters):
fig, ax1 = matplotlib.pyplot.subplots()
ax2 = ax1.twinx()
- for heater in heaters.split(','):
+ for heater in heaters.split(","):
heater = heater.strip()
- temp_key = heater + ':' + 'temp'
- target_key = heater + ':' + 'target'
- pwm_key = heater + ':' + 'pwm'
+ temp_key = heater + ":" + "temp"
+ target_key = heater + ":" + "target"
+ pwm_key = heater + ":" + "pwm"
times = []
temps = []
targets = []
@@ -263,45 +288,64 @@ def plot_temperature(data, heaters):
temp = d.get(temp_key)
if temp is None:
continue
- times.append(datetime.datetime.utcfromtimestamp(d['#sampletime']))
+ times.append(datetime.datetime.utcfromtimestamp(d["#sampletime"]))
temps.append(float(temp))
- pwm.append(float(d.get(pwm_key, 0.)))
- targets.append(float(d.get(target_key, 0.)))
- ax1.plot_date(times, temps, '-', label='%s temp' % (heater,), alpha=0.8)
+ pwm.append(float(d.get(pwm_key, 0.0)))
+ targets.append(float(d.get(target_key, 0.0)))
+ ax1.plot_date(times, temps, "-", label="%s temp" % (heater,), alpha=0.8)
if any(targets):
- label = '%s target' % (heater,)
- ax1.plot_date(times, targets, '-', label=label, alpha=0.3)
+ label = "%s target" % (heater,)
+ ax1.plot_date(times, targets, "-", label=label, alpha=0.3)
if any(pwm):
- label = '%s pwm' % (heater,)
- ax2.plot_date(times, pwm, '-', label=label, alpha=0.2)
+ label = "%s pwm" % (heater,)
+ ax2.plot_date(times, pwm, "-", label=label, alpha=0.2)
# Build plot
ax1.set_title("Temperature of %s" % (heaters,))
- ax1.set_xlabel('Time')
- ax1.set_ylabel('Temperature')
- ax2.set_ylabel('pwm')
+ ax1.set_xlabel("Time")
+ ax1.set_ylabel("Temperature")
+ ax2.set_ylabel("pwm")
fontP = matplotlib.font_manager.FontProperties()
- fontP.set_size('x-small')
+ fontP.set_size("x-small")
ax1li, ax1la = ax1.get_legend_handles_labels()
ax2li, ax2la = ax2.get_legend_handles_labels()
- ax1.legend(ax1li + ax2li, ax1la + ax2la, loc='best', prop=fontP)
- ax1.xaxis.set_major_formatter(matplotlib.dates.DateFormatter('%H:%M'))
+ ax1.legend(ax1li + ax2li, ax1la + ax2la, loc="best", prop=fontP)
+ ax1.xaxis.set_major_formatter(matplotlib.dates.DateFormatter("%H:%M"))
ax1.grid(True)
return fig
+
def main():
# Parse command-line arguments
usage = "%prog [options] <logfile>"
opts = optparse.OptionParser(usage)
- opts.add_option("-f", "--frequency", action="store_true",
- help="graph mcu frequency")
- opts.add_option("-s", "--system", action="store_true",
- help="graph system load")
- opts.add_option("-o", "--output", type="string", dest="output",
- default=None, help="filename of output graph")
- opts.add_option("-t", "--temperature", type="string", dest="heater",
- default=None, help="graph heater temperature")
- opts.add_option("-m", "--mcu", type="string", dest="mcu", default=None,
- help="limit stats to the given mcu")
+ opts.add_option(
+ "-f", "--frequency", action="store_true", help="graph mcu frequency"
+ )
+ opts.add_option("-s", "--system", action="store_true", help="graph system load")
+ opts.add_option(
+ "-o",
+ "--output",
+ type="string",
+ dest="output",
+ default=None,
+ help="filename of output graph",
+ )
+ opts.add_option(
+ "-t",
+ "--temperature",
+ type="string",
+ dest="heater",
+ default=None,
+ help="graph heater temperature",
+ )
+ opts.add_option(
+ "-m",
+ "--mcu",
+ type="string",
+ dest="mcu",
+ default=None,
+ help="limit stats to the given mcu",
+ )
options, args = opts.parse_args()
if len(args) != 1:
opts.error("Incorrect number of arguments")
@@ -333,5 +377,6 @@ def main():
fig.set_size_inches(8, 6)
fig.savefig(options.output)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
main()