ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Trigger
TrigValidation
TrigValTools
bin
trig-test-json.py
Go to the documentation of this file.
1
#!/usr/bin/env python
2
#
3
# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
4
#
5
6
# This script parses outputs of trigger nightly test post-processing steps
7
# and creates a JSON file with extra data other than result codes
8
# (which are handled by ART).
9
10
import
json
11
import
re
12
import
sys
13
import
logging
14
import
os
15
from
collections
import
OrderedDict
16
from
TrigValTools.TrigARTUtils
import
first_existing_file, newest_file
17
18
logging.basicConfig(stream=sys.stdout,
19
format=
'%(levelname)-8s %(message)s'
,
20
level=logging.INFO)
21
do_prmon =
True
22
mod_name =
''
23
try
:
24
mod_name =
'numpy'
25
import
numpy
as
np
26
mod_name =
'pandas'
27
from
pandas
import
read_csv
28
mod_name =
'scipy.optimize'
29
from
scipy.optimize
import
curve_fit
30
mod_name =
'matplotlib'
31
import
matplotlib
32
matplotlib.use(
'PDF'
)
33
import
matplotlib.pyplot
as
plt
34
except
Exception
as
e:
35
do_prmon =
False
36
logging.warning(
'Failed to import module %s, prmon output analysis will be skipped! %s'
, mod_name, e)
37
38
class
LastUpdatedOrderedDict
(OrderedDict):
39
'Store items in the order the keys were last added'
40
41
def
__setitem__
(self, key, value):
42
if
key
in
self:
43
del self[key]
44
OrderedDict.__setitem__(self, key, value)
45
46
def
get_num_from_checklog
(filename):
47
if
not
os.path.isfile(filename):
48
logging.warning(f
"Cannot open file {filename}"
)
49
return
None
50
with
open(filename)
as
logfile:
51
if
re.search(
"No error/warning messages found in.*$"
, logfile.read(), re.MULTILINE)
is
not
None
:
52
logging.debug(
"Number of errors/warnings: 0"
)
53
return
0
54
logfile.seek(0)
55
match = re.search(
r'Found (\d+) (\w+) message\(s\) in.*$'
, logfile.read(), re.MULTILINE)
56
if
match
is
None
:
57
logging.warning(f
"Cannot extract number of messages from {filename}"
)
58
return
None
59
logging.debug(f
"Number of {match[2]}s: {match[1]}"
)
60
return
int(match[1])
61
62
def
get_num_histos
(filename):
63
if
not
os.path.isfile(filename):
64
logging.warning(f
"Cannot open file {filename}"
)
65
return
None
66
with
open(filename)
as
logfile:
67
match = re.search(
r"Total histograms:.* (\d+)$"
, logfile.read(), re.MULTILINE)
68
if
match
is
None
:
69
logging.warning(
"Cannot extract number of histograms from {}"
.
format
(filename))
70
return
None
71
logging.debug(f
"Found {match[1]} histograms"
)
72
return
int(match[1])
73
74
def
convert_to_megabytes
(number, unit):
75
multipliers = {
76
'B'
: 1.0/(1024**2),
77
'kB'
: 1.0/1024,
78
'MB'
: 1,
79
"GB"
: 1024,
80
'TB'
: 1024**2
81
}
82
for
unit_name, mult
in
multipliers.items():
83
if
unit_name == unit:
84
return
float(number)*mult
85
logging.error(
"Unit conversion failed from {} to MB"
.
format
(unit))
86
return
None
87
88
89
def
extract_mem_perfmon
(line):
90
words = line[0].
split
()
91
mem_end = words[5:7]
92
logging.debug(
"mem_end = {}"
.
format
(mem_end))
93
mem_delta = words[8:10]
94
logging.debug(
"mem_delta = {}"
.
format
(mem_delta))
95
mem_mb =
convert_to_megabytes
(mem_end[0], mem_end[1])
96
logging.debug(
"mem_mb = {}"
.
format
(mem_mb))
97
delta_mb =
convert_to_megabytes
(mem_delta[0], mem_delta[1])
98
logging.debug(
"delta_mb = {}"
.
format
(delta_mb))
99
return
mem_mb, delta_mb
100
101
102
def
analyse_perfmon
(filename):
103
if
not
os.path.isfile(filename):
104
logging.warning(
"Cannot open file {}"
.
format
(filename))
105
return
None
106
with
open(filename)
as
logfile:
107
first_line = -1
108
last_line = -1
109
all_lines = logfile.readlines()
110
for
i, line
in
enumerate(all_lines):
111
if
first_line >= 0
and
last_line >= 0:
112
break
113
if
"=== [evt - slice] ==="
in
line:
114
first_line = i
115
elif
"=== [fin - slice] ==="
in
line:
116
last_line = i
117
if
first_line < 0
or
last_line < 0:
118
logging.warning(
"Cannot extract memory usage information from {}"
.
format
(filename))
119
return
None
120
evt_mon_lines = all_lines[first_line:last_line]
121
vmem_line = re.findall(
"^VMem.*$"
,
'\n'
.join(evt_mon_lines), re.MULTILINE)
122
rss_line = re.findall(
"^RSS.*$"
,
'\n'
.join(evt_mon_lines), re.MULTILINE)
123
logging.debug(
"vmem_line = {}"
.
format
(vmem_line))
124
logging.debug(
"rss_line = {}"
.
format
(rss_line))
125
if
len(vmem_line) == 0:
126
logging.warning(
"Cannot extract VMem information from {}"
.
format
(filename))
127
if
len(rss_line) == 0:
128
logging.warning(
"Cannot extract RSS information from {}"
.
format
(filename))
129
vmem, dvmem =
extract_mem_perfmon
(vmem_line)
130
rss, drss =
extract_mem_perfmon
(rss_line)
131
data =
LastUpdatedOrderedDict
()
132
data[
'vmem'
] =
"{0:.3f}"
.
format
(vmem)
133
data[
'delta-vmem'
] =
"{0:.3f}"
.
format
(dvmem)
134
data[
'rss'
] =
"{0:.3f}"
.
format
(rss)
135
data[
'delta-rss'
] =
"{0:.3f}"
.
format
(drss)
136
return
data
137
138
139
def
mem_func
(x_arr, x_trans, init_slope, exec_slope):
140
retval = []
141
for
x
in
x_arr:
142
if
x < x_trans:
143
retval.append(init_slope * x)
144
else
:
145
retval.append(exec_slope * x + (init_slope - exec_slope) * x_trans)
146
return
retval
147
148
149
def
find_dmem_prmon
(xdata, ydata, label, filename):
150
popt, pcov = curve_fit(mem_func, xdata, ydata, bounds=(0, [0.9*
max
(xdata), np.inf, np.inf]))
151
logging.debug(
"Fit result: %s"
, str(popt))
152
plot_prmon
(xdata, ydata, label, filename, popt)
153
x_trans = popt[0]
154
x_last = xdata.iloc[-1]
155
dmem_v =
mem_func
([x_last, x_trans], popt[0], popt[1], popt[2])
156
return
dmem_v[0] - dmem_v[1]
157
158
159
def
plot_prmon
(xdata, ydata, name, filename, params=[]):
160
plt.plot(xdata, ydata,
'b-'
, label=name)
161
if
len(params)>0:
162
plt.plot(xdata,
mem_func
(xdata, *params),
'r-'
, label=
'{:s} fit, exec slope={:.2f} kB/s'
.
format
(name, params[2]))
163
plt.xlabel(
'wtime [s]'
)
164
plt.ylabel(name+
' [kB]'
)
165
plt.legend()
166
plt.title(
'{:s} from {:s}'
.
format
(name, filename))
167
plt.savefig(
'prmon_{:s}.pdf'
.
format
(name), bbox_inches=
'tight'
)
168
plt.clf()
169
170
171
def
analyse_prmon
(filename):
172
try
:
173
prmon_data = read_csv(filename, sep=
'\t'
)
174
except
IOError:
175
logging.warning(
"Cannot open file {}"
.
format
(filename))
176
return
None
177
time_v = prmon_data[
'wtime'
]
178
pss_v = prmon_data[
'pss'
]
179
rss_v = prmon_data[
'rss'
]
180
vmem_v = prmon_data[
'vmem'
]
181
data =
LastUpdatedOrderedDict
()
182
data[
'vmem'
] =
"{0:.3f}"
.
format
(
convert_to_megabytes
(
max
(vmem_v),
'kB'
))
183
data[
'rss'
] =
"{0:.3f}"
.
format
(
convert_to_megabytes
(
max
(rss_v),
'kB'
))
184
data[
'pss'
] =
"{0:.3f}"
.
format
(
convert_to_megabytes
(
max
(pss_v),
'kB'
))
185
if
len(time_v) < 80:
186
logging.info(
'Not enough prmon data points, skipping memory slope fitting'
)
187
# Save plots without fitting and return
188
plot_prmon
(time_v, pss_v,
'pss'
, filename)
189
plot_prmon
(time_v, rss_v,
'rss'
, filename)
190
plot_prmon
(time_v, vmem_v,
'vmem'
, filename)
191
return
data
192
d_pss =
find_dmem_prmon
(time_v, pss_v,
'pss'
, filename)
193
d_rss =
find_dmem_prmon
(time_v, rss_v,
'rss'
, filename)
194
d_vmem =
find_dmem_prmon
(time_v, vmem_v,
'vmem'
, filename)
195
data[
'delta-vmem'
] =
"{0:.3f}"
.
format
(
convert_to_megabytes
(d_vmem,
'kB'
))
196
data[
'delta-rss'
] =
"{0:.3f}"
.
format
(
convert_to_megabytes
(d_rss,
'kB'
))
197
data[
'delta-pss'
] =
"{0:.3f}"
.
format
(
convert_to_megabytes
(d_pss,
'kB'
))
198
return
data
199
200
201
def
main
():
202
data =
LastUpdatedOrderedDict
()
203
204
# Get number of errors
205
checklog_log = first_existing_file([
'checklog.log'
,
'CheckLog.log'
])
206
ne =
get_num_from_checklog
(checklog_log)
if
checklog_log
else
None
207
logging.debug(
"ne: {}"
.
format
(ne))
208
if
ne
is
None
:
209
logging.warning(
"Failed to read number of errors from the log"
)
210
data[
'num-errors'
] =
'n/a'
211
else
:
212
data[
'num-errors'
] = ne
213
214
# Get number of warnings
215
warnings_log = first_existing_file([
'warnings.log'
,
'Warnings.log'
])
216
nw =
get_num_from_checklog
(warnings_log)
if
warnings_log
else
None
217
logging.debug(
"nw: {}"
.
format
(nw))
218
if
nw
is
None
:
219
logging.warning(
"Failed to read number of warnings from the log"
)
220
data[
'num-warnings'
] =
'n/a'
221
else
:
222
data[
'num-warnings'
] = nw
223
224
# Get number of histograms
225
histcount_log = first_existing_file([
'histSizes.log'
,
'HistCount.log'
])
226
nh =
get_num_histos
(histcount_log)
if
histcount_log
else
None
227
logging.debug(
"nh: {}"
.
format
(nh))
228
if
nh
is
None
:
229
logging.warning(
"Failed to read number of histograms from the log"
)
230
data[
'num-histograms'
] =
'n/a'
231
else
:
232
data[
'num-histograms'
] = nh
233
234
# Get memory usage information from prmon
235
if
do_prmon:
236
prmon_log = newest_file(
r'prmon\..*\.txt'
)
237
if
not
prmon_log:
238
prmon_log = first_existing_file([
'prmon.full.RDOtoRDOTrigger'
,
'prmon.full.RAWtoESD'
,
'prmon.full.ESDtoAOD'
,
'prmon.full.RAWtoALL'
])
239
if
not
prmon_log:
240
logging.info(
"No prmon output found, the result will be empty"
)
241
data[
'prmon'
] =
'n/a'
242
else
:
243
logging.info(
"Analysing prmon output from %s"
, prmon_log)
244
prmon_data =
analyse_prmon
(prmon_log)
245
if
prmon_data
is
None
:
246
logging.warning(
"Could not analyse prmon output, the result will be empty"
)
247
data[
'prmon'
] =
'n/a'
248
else
:
249
data[
'prmon'
] = prmon_data
250
251
# Get memory usage information from PerfMon
252
perfmon_log = newest_file(
r'.*perfmon\.summary\.txt'
)
253
if
not
perfmon_log:
254
logging.info(
"No PerfMon output found, the result will be empty"
)
255
data[
'memory-usage'
] =
'n/a'
256
else
:
257
logging.info(
"Analysing PerfMon output from %s"
, perfmon_log)
258
perfmon_data =
analyse_perfmon
(perfmon_log)
259
if
perfmon_data
is
None
:
260
logging.warning(
"Could not analyse PerfMon output, the result will be empty"
)
261
data[
'memory-usage'
] =
'n/a'
262
else
:
263
data[
'memory-usage'
] = perfmon_data
264
265
# Save data to JSON file
266
with
open(
'extra-results.json'
,
'w'
)
as
outfile:
267
json.dump(data, outfile, indent=4)
268
269
270
if
"__main__"
in
__name__:
271
sys.exit(
main
())
max
#define max(a, b)
Definition
cfImp.cxx:41
trig-test-json.LastUpdatedOrderedDict
Definition
trig-test-json.py:38
trig-test-json.LastUpdatedOrderedDict.__setitem__
__setitem__(self, key, value)
Definition
trig-test-json.py:41
split
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition
hcg.cxx:179
trig-test-json.plot_prmon
plot_prmon(xdata, ydata, name, filename, params=[])
Definition
trig-test-json.py:159
trig-test-json.get_num_histos
get_num_histos(filename)
Definition
trig-test-json.py:62
trig-test-json.main
main()
Definition
trig-test-json.py:201
trig-test-json.analyse_prmon
analyse_prmon(filename)
Definition
trig-test-json.py:171
trig-test-json.get_num_from_checklog
get_num_from_checklog(filename)
Definition
trig-test-json.py:46
trig-test-json.find_dmem_prmon
find_dmem_prmon(xdata, ydata, label, filename)
Definition
trig-test-json.py:149
trig-test-json.extract_mem_perfmon
extract_mem_perfmon(line)
Definition
trig-test-json.py:89
trig-test-json.format
format
Definition
trig-test-json.py:19
trig-test-json.convert_to_megabytes
convert_to_megabytes(number, unit)
Definition
trig-test-json.py:74
trig-test-json.mem_func
mem_func(x_arr, x_trans, init_slope, exec_slope)
Definition
trig-test-json.py:139
trig-test-json.analyse_perfmon
analyse_perfmon(filename)
Definition
trig-test-json.py:102
Generated on
for ATLAS Offline Software by
1.17.0