From 80f905ceba540a83dcf8d65de2a027c50b30d3b9 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 15 Jun 2015 09:20:05 -0700 Subject: [PATCH] toplev: Support --columns in csv mode --- README.md | 1 + tl-tester | 1 + toplev.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f3baac6f..38e70afe 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ analysis on Intel CPUs on top of [Linux perf](https://perf.wiki.kernel.org/index # Recent new features: +* toplev now supports columnar output in CSV mode (-x, --column) * toplev can print the critical bottleneck with --bottleneck * The tools can now find event lists for the original user of sudo * jevents now has a perf stat like tool called jstat (renamed to jestat) diff --git a/tl-tester b/tl-tester index 251d1fc7..55bd73d8 100755 --- a/tl-tester +++ b/tl-tester @@ -106,6 +106,7 @@ EVENTMAP=${cpus[hsw]} FORCECPU=hsw $WRAP ./toplev.py --graph -o x.png -d --metri fi EVENTMAP=${cpus[ivb]} FORCECPU=ivb $WRAP ./toplev.py -d -l4 -I 100 sleep 1 EVENTMAP=${cpus[ivb]} FORCECPU=ivb $WRAP ./toplev.py -d -l4 -I 100 --columns sleep 1 +EVENTMAP=${cpus[ivb]} FORCECPU=ivb $WRAP ./toplev.py -d -l4 -I 100 --columns -x, sleep 1 EVENTMAP=${cpus[ivb]} FORCECPU=ivb $WRAP ./toplev.py -d -l4 --valcsv val.csv --user $LOAD | tee log grep :u log grep /u log diff --git a/toplev.py b/toplev.py index d281fb87..a8ddc21b 100755 --- a/toplev.py +++ b/toplev.py @@ -532,6 +532,57 @@ def flush(self): self.print_desc(desc, sample) self.nodes = dict() +class OutputColumnsCSV(OutputColumns): + """Columns output in CSV mode.""" + + def __init__(self, logfile, sep): + OutputColumns.__init__(self, logfile) + self.writer = csv.writer(self.logf, delimiter=sep) + self.printed_header = False + + def show(self, timestamp, title, area, hdr, s, remark, desc, sample, valstat): + self.timestamp = timestamp + key = (area, hdr) + if key not in self.nodes: + self.nodes[key] = dict() + assert title not in self.nodes[key] + self.nodes[key][title] = (s, remark, desc, sample, valstat) + + def flush(self): + cpunames = sorted(self.cpunames) + if not self.printed_header: + ts = ["Timestamp"] if self.timestamp else [] + self.writer.writerow(ts + ["Area", "Node"] + cpunames + ["Description", "Sample", "Stddev", "Multiplex"]) + self.printed_header = True + for key in sorted(sorted(self.nodes.keys(), key=lambda x: x[1]), key=lambda x: x[0] == ""): + node = self.nodes[key] + ts = [self.timestamp] if self.timestamp else [] + l = ts + [key[0], key[1]] + vlist = [] + ol = dict() + desc, sample = "", "" + for cpuname in cpunames: + if cpuname in node: + cpu = node[cpuname] + if cpu[2]: + desc = cpu[2] + if cpu[3]: + sample = cpu[3] + # ignore remark for now + if cpu[4]: + vlist.append(cpu[4]) + ol[cpuname] = float(cpu[0]) + l += [ol[x] if x in ol else "" for x in cpunames] + l.append(desc) + l.append(sample) + vs = combine_valstat(vlist) + if vs: + l += (vs.stddev, vs.multiplex if not isnan(vs.multiplex) else "") + else: + l += ["", ""] + self.writer.writerow(l) + self.nodes = dict() + class OutputCSV(Output): """Output data in CSV format.""" def __init__(self, logfile, sep): @@ -1784,7 +1835,10 @@ def setup_with_metrics(p, runner): runner.collect() if csv_mode: - out = OutputCSV(args.output, csv_mode) + if args.columns: + out = OutputColumnsCSV(args.output, csv_mode) + else: + out = OutputCSV(args.output, csv_mode) elif args.columns: out = OutputColumns(args.output) else: