-
Notifications
You must be signed in to change notification settings - Fork 336
/
tl-xlsx.py
executable file
·223 lines (207 loc) · 8.43 KB
/
tl-xlsx.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#!/usr/bin/env python3
# Copyright (c) 2020, Intel Corporation
# Author: Andi Kleen
#
# 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.
#
# convert toplev output to xlsx files using xlsxwriter
# toplev.py --all --valcsv xv.log --perf-output xp.log -A -a --split-output --per-socket --global --summary \
# --per-core --per-thread -x, -o x.log -I 1000 sleep 10
# tl_xlsx.py --valcsv xv.log --perf xp.log --socket x-socket.log --global x-global.log --core x-core.log --thread x-thread.log x.xlsx
from __future__ import print_function
import sys
import argparse
import re
import collections
import csv
try:
import xlsxwriter
except ImportError:
sys.exit("Please install xlswriter with 'pip%s install xlsxwriter'" % sys.version[0])
import gen_level
ap = argparse.ArgumentParser(description="Convert toplev CSV files to xlsx")
ap.add_argument('xlsxfile', help="xlsx output name")
ap.add_argument('--socket', type=argparse.FileType('r'), help="toplev socket csv file", metavar="csvfile")
ap.add_argument('--global', type=argparse.FileType('r'), help="toplev global csv file", dest='global_', metavar="csvfile")
ap.add_argument('--core', type=argparse.FileType('r'), help="toplev core csv file", metavar="csvfile")
ap.add_argument('--program', type=argparse.FileType('r'), help="toplev program csv file", metavar="csvfile")
ap.add_argument('--thread', type=argparse.FileType('r'), help="toplev thread csv file", metavar="csvfile")
ap.add_argument('--add', nargs=2, help="toplev thread generic csv file. Specify csvfile and sheet name as two arguments",
metavar="name", action="append")
ap.add_argument('--valcsv', type=argparse.FileType('r'), help="toplev valcsv input file", metavar="csvfile")
ap.add_argument('--perf', type=argparse.FileType('r'), help="toplev perf values csv file")
ap.add_argument('--cpuinfo', type=argparse.FileType('r'), help="cpuinfo file")
ap.add_argument('--chart', help="add sheet with plots of normalized sheet. argument is normalied sheet name",
action="append")
ap.add_argument('--no-summary', help='Do not generate summary charts', action='store_true')
args = ap.parse_args()
workbook = xlsxwriter.Workbook(args.xlsxfile, {'constant_memory': True})
bold = workbook.add_format({'bold': True})
valueformat = workbook.add_format({'num_format': '###,###,###,###,##0.0'})
valueformat_bold = workbook.add_format({'num_format': '###,###,###,###,##0.0',
'bold': True})
#valueformat.set_num_format(1)
def set_columns(worksheet, c, lengths):
for col, j in enumerate(c):
if j == "Value":
j = " " * 18
if j == "Description":
j = "Descr"
lengths[col] = max(len(j) + 5, lengths[col])
worksheet.set_column(col, col, lengths[col])
worksheets = {}
rows = {}
headers = {}
def get_worksheet(name):
if name in worksheets:
return worksheets[name]
worksheet = workbook.add_worksheet(name)
worksheets[name] = worksheet
rows[name] = 1
return worksheet
def to_float(n):
if re.match(r'-?[,.0-9]+$', n):
n = float(n)
return n
def create_sheet(name, infh, delimiter=',', version=None):
lengths = collections.defaultdict(lambda: 0)
worksheet = get_worksheet(name)
cf = csv.reader(infh, delimiter=delimiter)
row = 0
title = {}
titlerow = []
summary = False
for c in cf:
if len(c) > 0 and len(c[0]) > 0 and c[0][0] == "#":
version = c
continue
if row == 0:
title = collections.OrderedDict()
for i, k in enumerate(c):
title[k] = i
titlerow = c
headers[name] = title
if row < 10:
set_columns(worksheet, c, lengths)
if not summary and len(c) > 0 and c[0] == "SUMMARY":
if args.no_summary:
continue
rows[name] = row
sname = name + " summary"
worksheet = get_worksheet(sname)
set_columns(worksheet, c, lengths)
worksheet.write_row(0, 0, titlerow)
headers[sname] = titlerow
row = rows[sname]
summary = True
elif summary and len(c) > 0 and c[0] != "SUMMARY" and c[0][0] != "#":
worksheet = get_worksheet(name)
summary = False
rows[sname] = row
row = rows[name]
c = list(map(to_float, c))
worksheet.write_row(row, 0, c)
isbn = False
if "Bottleneck" in title:
bn = title["Bottleneck"]
if len(c) > bn and c[bn] == "<==":
worksheet.write(row, title["Area"], c[title["Area"]], bold)
worksheet.write(row, title["Value"], c[title["Value"]], bold)
if "CPUs" in title:
worksheet.write(row, title["CPUs"], c[title["CPUs"]], bold)
isbn = True
worksheet.write(row, bn, c[bn], bold)
if "Value" in title and len(c) > title["Value"] and isinstance(c[title["Value"]], float):
worksheet.write_number(row, title["Value"], c[title["Value"]],
valueformat_bold if isbn else valueformat)
elif "0" in title:
num = 0
while num in title:
col = title["%d" % num]
if len(c) > col and re.match(r'[0-9]+', c[col]):
worksheet.write_number(row, col, float(c[col]), valueformat)
num += 1
row += 1
return version
ROW_SCALE = 18
MIN_ROWS = 15
GRAPH_ROWS = 15
def gen_chart(source):
if source not in headers:
print("source %s for chart not found" % source, file=sys.stderr)
return
worksheet = get_worksheet(source + " chart")
charts = collections.OrderedDict()
for n, ind in headers[source].items():
if n == "Timestamp":
continue
ns = n.split()
if len(ns) > 1:
prefix = ns[0] + " "
nn = " ".join(ns[1:])
else:
prefix = ''
nn = n
if gen_level.is_metric(nn):
chart = workbook.add_chart({'type': 'line'})
charts[n] = chart
chart.set_title({'name': n})
else:
key = n[:n.rindex('.')] if '.' in n else prefix
if key not in charts:
charts[key] = workbook.add_chart(
{'type': 'column', 'subtype': 'percent_stacked' })
chart = charts[key]
chart.set_title({
'name': '%s Level %d %s' % (prefix, n.count('.') + 1,
key[key.index(' '):] if ' ' in key else key) })
chart.set_x_axis({'name': 'Timestamp'})
chart.add_series({
'name': [source, 0, ind],
'categories': [source, 1, 0, rows[source], 0],
'values': [source, 1, ind, rows[source], ind]
})
chart.set_size({'width': (rows[source] + MIN_ROWS ) * ROW_SCALE})
chart.set_legend({
'overlay': True,
'layout': { 'x': 0.01, 'y': 0.01, 'width': 0.12, 'height': 0.12 },
'fill': { 'none': True, 'transparency': True }
})
row = 1
for j in charts.keys():
worksheet.insert_chart('A%d' % row, charts[j])
row += GRAPH_ROWS
version = None
if args.global_:
version = create_sheet("global", args.global_, version=version)
if args.socket:
version = create_sheet("socket", args.socket, version=version)
if args.core:
version = create_sheet("core", args.core, version=version)
if args.thread:
version = create_sheet("thread", args.thread, version=version)
if args.program:
version = create_sheet("prog", args.program, version=version)
if args.add:
for fn, name in args.add:
version = create_sheet(name, open(fn), version=version)
if args.chart:
for cname in args.chart:
gen_chart(cname)
if args.valcsv:
create_sheet("event values", args.valcsv)
if args.perf:
create_sheet("raw perf output", args.perf, delimiter=';')
if args.cpuinfo:
create_sheet("cpuinfo", args.cpuinfo, delimiter=':')
if version:
worksheet = workbook.add_worksheet("version")
worksheet.write_row(0, 0, version)
workbook.close()