ATLAS Offline Software
Loading...
Searching...
No Matches
perfmonmt-printer.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2
3# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
4
5import json
6import argparse
7import tarfile
8
9# Print Header
11 print('='*105)
12 print('{0:^105}'.format('PerfMonMTSvc Report'))
13 print('='*105)
14 print('{0:<105}'.format('IMPORTANT : PLEASE NOTE THAT THIS SERVICE IS CURRENTLY IN R&D PHASE.'))
15 print('{0:<105}'.format(' FOR FURTHER INFORMATION/QUERIES PLEASE GET IN TOUCH WITH THE SPOT TEAM.'))
16 print('='*105)
17
18# Print Footer
20 print('='*105)
21 print('{0:^105}'.format('ALL DONE!'))
22 print('='*105)
23
24# Print Component Level Data in Descending Order
25def printComponentLevelInfo(execOnly = True, orderBy = 'cpuTime', maxComps = -1):
26 if 'componentLevel' not in data:
27 return
28 print('='*105)
29 print('{0:^105}'.format('Component Level Monitoring'))
30 print('='*105)
31 print('{0:<18}{1:<10}{2:<20}{3:<20}{4:<20}{5:<20}'.format('Step',
32 'Count',
33 'CPU Time [ms]',
34 'Vmem [kB]',
35 'Malloc [kB]',
36 'Component'))
37 print('='*105)
38 steps = ['Initialize', 'FirstEvent', 'Execute', 'Finalize', 'Callback', 'preLoadProxy']
39 if execOnly:
40 steps = ['Execute']
41 ncomps = 0
42 for step in steps:
43 try:
44 for entry in sorted(data['componentLevel'][step],
45 key=lambda x: data['componentLevel'][step][x][orderBy], reverse = True):
46 print('{0:<18}{1:<10}{2:<20.2f}{3:<20}{4:<20}{5:<20}'.format(step,
47 data['componentLevel'][step][entry]['count'],
48 data['componentLevel'][step][entry]['cpuTime'],
49 data['componentLevel'][step][entry]['vmem'],
50 data['componentLevel'][step][entry]['malloc'],
51 entry))
52 ncomps += 1
53 if (ncomps == maxComps):
54 break
55 except KeyError:
56 pass
57 print('='*105)
58
59# Event Level Data in Ascending Order
61 if 'eventLevel' not in data:
62 return
63 print('='*105)
64 print('{0:^105}'.format('Event Level Monitoring'))
65 print('='*105)
66 print('{0:^15}{1:^15}{2:^15}{3:^15}{4:^15}{5:^15}{6:^15}'.format('Event',
67 'CPU [s]',
68 'Wall [s]',
69 'Vmem [kB]',
70 'Rss [kB]',
71 'Pss [kB]',
72 'Swap [kB]'))
73 print('='*105)
74 for entry in sorted(data['eventLevel'], key=float):
75 print('{0:^15}{1:^15.2f}{2:^15.2f}{3:^15}{4:^15}{5:^15}{6:^15}'.format(entry,
76 data['eventLevel'][entry]['cpuTime']*0.001,
77 data['eventLevel'][entry]['wallTime']*0.001,
78 data['eventLevel'][entry]['vmem'],
79 data['eventLevel'][entry]['rss'],
80 data['eventLevel'][entry]['pss'],
81 data['eventLevel'][entry]['swap']))
82# Snapshots Summary
84 if 'summary' not in data:
85 return
86 if 'snapshotLevel' not in data['summary']:
87 return
88 print('='*105)
89 print('{0:^105}'.format('Snapshots Summary'))
90 print('='*105)
91 print('{0:<14}{1:<13}{2:<13}{3:<13}{4:<13}{5:<13}{6:<13}{7:<13}'.format('Step',
92 'dCPU [s]',
93 'dWall [s]',
94 '<CPU>',
95 'dVmem [kB]',
96 'dRss [kB]',
97 'dPss [kB]',
98 'dSwap [kB]'))
99 print('-'*105)
100 for entry in ['Configure', 'Initialize', 'FirstEvent', 'Execute', 'Finalize']:
101 print('{0:<14}{1:<13.2f}{2:<13.2f}{3:<13.2f}{4:<13}{5:<13}{6:<13}{7:<13}'.format(entry,
102 data['summary']['snapshotLevel'][entry]['dCPU']*0.001,
103 data['summary']['snapshotLevel'][entry]['dWall']*0.001,
104 data['summary']['snapshotLevel'][entry]['cpuUtil'],
105 data['summary']['snapshotLevel'][entry]['dVmem'],
106 data['summary']['snapshotLevel'][entry]['dRss'],
107 data['summary']['snapshotLevel'][entry]['dPss'],
108 data['summary']['snapshotLevel'][entry]['dSwap']))
109 print('*'*105)
110 print('{0:<40}{1:<}'.format('Number of events processed:',
111 data['summary']['nEvents']))
112 nEvents = float(data['summary']['nEvents'])
113 cpuExec = float(data['summary']['snapshotLevel']['FirstEvent']['dCPU']) + float(data['summary']['snapshotLevel']['Execute']['dCPU'])
114 wallExec = float(data['summary']['snapshotLevel']['FirstEvent']['dWall']) + float(data['summary']['snapshotLevel']['Execute']['dWall'])
115 print('{0:<40}{1:<.0f}'.format('CPU usage per event [ms]:', cpuExec/nEvents))
116 print('{0:<40}{1:<.3f}'.format('Events per second:', nEvents/wallExec*1000.))
117 print('{0:<40}{1:<}'.format('CPU utilization efficiency [%]:', data['summary']['misc']['cpuUtilEff']))
118 print('*'*105)
119 print('{0:<40}{1:<.2f} GB'.format('Max Vmem:',
120 float(data['summary']['peaks']['vmemPeak'])/1024./1024.))
121 print('{0:<40}{1:<.2f} GB'.format('Max Rss:',
122 float(data['summary']['peaks']['rssPeak'])/1024./1024))
123 print('{0:<40}{1:<.2f} GB'.format('Max Pss:',
124 float(data['summary']['peaks']['pssPeak'])/1024./1024.))
125 print('*'*105)
126 print('{0:<40}{1:<.2f} MB'.format('Leak estimate per event Vmem:',
127 float(data['summary']['leakEstimates']['vmemLeak'])/1024.))
128 print('{0:<40}{1:<.2f} MB'.format('Leak estimate per event Pss:',
129 float(data['summary']['leakEstimates']['pssLeak'])/1024.))
130 print(' >> Estimated using the last {0} measurements from the Event Level Monitoring'.format(data['summary']['leakEstimates']['nPoints']))
131 print(' >> Events prior to the first 25 are omitted...')
132
133# Print System Info
135 print('='*105)
136 print('{0:^105}'.format('System Information'))
137 print('='*105)
138 print('{0:<40}{1:<}'.format('CPU Model:',data['summary']['sysInfo']['cpuModel'].lstrip()))
139 print('{0:<40}{1:<}'.format('Number of Available Cores:',data['summary']['sysInfo']['coreNum']))
140 print('{0:<40}{1:<.2f} GB'.format('Total Memory:',float(data['summary']['sysInfo']['totMem'])/1024./1024.))
141 print('='*105)
142
143# Print Environment Info
145 print('='*105)
146 print('{0:^105}'.format('Environment Information'))
147 print('='*105)
148 print('{0:<40}{1:<}'.format('Malloc Library:',data['summary']['envInfo']['mallocLib']))
149 print('{0:<40}{1:<}'.format('Math Library:',data['summary']['envInfo']['mathLib']))
150 print('='*105)
151
152# Print out data
153def printReport(data):
154
156
157 # Print Component Level Data
158 if args.level in ['All', 'ComponentLevel']:
159 printComponentLevelInfo(args.exec_only,
160 args.order_by,
161 args.max_comps)
162
163 # Print Event Level Data
164 if args.level in ['All', 'EventLevel']:
166
167 # Print Snapshots Summary
168 if args.level in ['All', 'SummaryLevel']:
170
171 # Print System and Environment Information
172 if args.level in ['All']:
175 # Print Footer
177
178# Main function
179if '__main__' in __name__:
180
181 # Parse the user input
182 parser = argparse.ArgumentParser(description = 'Script to print tables using PerfMonMTSvc JSON')
183
184 parser.add_argument('-i', '--input', type = str, required = True,
185 help = 'PerfMonMTSvc JSON file')
186 parser.add_argument('-l', '--level', nargs = '?', default = 'All',
187 choices = ['All', 'SummaryLevel', 'EventLevel', 'ComponentLevel'],
188 help = 'Sets the level of detail in the printout')
189 parser.add_argument('-e', '--exec-only', dest = 'exec_only', action = 'store_true',
190 help = 'Print only the execute step for the components')
191 parser.add_argument('-o', '--order-by', dest = 'order_by', nargs = '?', default = 'cpuTime',
192 choices = ['cpuTime', 'vmem', 'malloc'],
193 help = 'Order components by a specific metric')
194 parser.add_argument('-m', '--max-components', dest = 'max_comps', type = int, default = -1,
195 help = 'The maximum number of compoments to be printed '
196 '(default: -1)')
197
198 args = parser.parse_args()
199
200 # Load the data and print the requested information
201 if tarfile.is_tarfile(args.input):
202
203 tar = tarfile.open(args.input)
204 #If data is tarred, there could be more than one json in the tar file: cycle through all
205 for member in tar.getmembers():
206 f = tar.extractfile(member)
207 data = json.load(f)
208 printReport(data)
209
210 tar.close()
211
212 #if it is a json file, proceed as normal
213 else:
214
215 with(open(args.input)) as json_file:
216 data = json.load(json_file)
217 printReport(data)
void print(char *figname, TCanvas *c1)
printComponentLevelInfo(execOnly=True, orderBy='cpuTime', maxComps=-1)