ATLAS Offline Software
Loading...
Searching...
No Matches
vmem-sz.py
Go to the documentation of this file.
1#!/usr/bin/env python
2
3# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
4
5__author__ = "Sebastien Binet <binet@cern.ch>"
6__doc__ = "get the inclusive and exclusive vmem sizes of a library"
7
8
9import argparse
10import ctypes
11import os
12
13
14from PyUtils.Decorators import forking as forking
15from PerfMonComps.PyMonUtils import loaded_libs, pymon
16
17_veto_libs = [
18 'resource.so', # from python std-lib 'resource'...
19 ]
20
21def lib_loader(libname):
22 return ctypes.cdll.LoadLibrary(libname)
23
24@forking
25def load_lib (libname):
26 _,vmem0,_ = pymon()
27 lib_loader (libname)
28 _,vmem1,_ = pymon()
29 libs = [l for l in loaded_libs()
30 if not os.path.basename(l) in _veto_libs and
31 os.access(l, os.R_OK)]
32 return (vmem0, vmem1, libs)
33
34@forking
35def dep_libs(libname):
36 """retrieve the list of dependencies of a given library
37 both direct and indirect dependencies
38 """
39 bkg_libs = [os.path.basename(l) for l in loaded_libs()]
40 bkg_libs = [l for l in bkg_libs if l not in _veto_libs]
41
42 _,_,libs = load_lib(libname)
43 libs = [os.path.basename(l) for l in libs]
44 return [l for l in libs if l not in bkg_libs and l!=libname]
45
46@forking
47def analyze (libname):
48 bkg_libs = loaded_libs()
49 #print ("::: bkg_libs:",map(os.path.basename, bkg_libs))
50 vmem0,vmem1,libs = load_lib (libname)
51 dVmemOffset = vmem1-vmem0
52 #print ("vmem0=%s vmem1=%s libs=%s" % (vmem0, vmem1, len(libs)))
53 linked_libs = [os.path.basename(lib)
54 for lib in libs
55 if (not (lib in bkg_libs) and
56 os.path.basename(lib) != os.path.basename(libname)
57 and os.access(lib, os.R_OK))]
58 #print ("::: linked_libs:",linked_libs)
59
60 # load all linked-in libs
61 def load_linked_in_libs(linked_libs):
62 all_good = True
63 for l in linked_libs:
64 try:
65 #print (" - loading [%s]..." % l)
66 lib_loader (l)
67 except Exception as err:
68 print ("** problem loading [%s]\n%s" % (l,err))
69 all_good = False
70 pass
71 return all_good
72 #print ("--> loading all linked-in libs...")
73 NRETRY = 10
74 for _ in range(NRETRY):
75 ok = load_linked_in_libs(linked_libs)
76 if ok:
77 break
78 else:
79 print ("** err: could not reliably load all libs (after %s retries)"%NRETRY)
80
81 #print ("--> loading all linked-in libs... [done]")
82
83 vmem0,vmem1,libs = load_lib (libname)
84 #print ("vmem0=%s vmem1=%s libs=%s" % (vmem0, vmem1, len(libs)))
85 dVmemLib = vmem1-vmem0
86 return (dVmemLib, dVmemOffset, len(linked_libs), len(bkg_libs))
87
88@forking
89def analyze_libraries (libnames, detailed=False):
90 display = []
91 _print = display.append
92 lib_stats = {}
93 for libname in libnames:
94 _print(":"*80)
95 bname = os.path.basename(libname)
96 _print(":: inspecting library: %s" % bname)
97 stats = analyze (libname)
98 _print(":: nbr linked: %s" % stats[2])
99 _print(":: dVmem-self: %8.3f Mb" % stats[0])
100 _print(":: dVmem-all : %8.3f Mb" % stats[1])
101 #print (":: bkg-libs: %s" % stats[3])
102 lib_stats[bname] = dict(
103 vmem_self= stats[0],
104 vmem_all= stats[1],
105 nbr_linked= stats[2],
106 )
107 if detailed:
108 import operator as _op
109 deps = dep_libs(libname)
110 dep_stats = dict((d, analyze(d)[:2]) for d in deps)
111 dep_vmem = dep_stats.items()
112 dep_vmem.sort(key=_op.itemgetter(1), reverse=True)
113 _print(":: deps: lib-self | lib-all:")
114 for k,v in dep_vmem:
115 _print(":: --> [%8.3f |%8.3f Mb] (%s)" % (v[0], v[1], k))
116
117 return display,lib_stats
118
119def save_stats (lib_stats, fname=None):
120 if fname is None:
121 fname = "vmem-stats-sz.csv"
122 print (":: saving vmem statistics in [%s]..."%fname)
123 import csv, os
124 if os.path.exists (fname):
125 os.remove (fname)
126 o = csv.writer (open(fname, "w"), delimiter=';')
127 o.writerow (['nbr libraries', len(lib_stats)])
128 o.writerow (['lib name', 'dvmem-self (Mb)', 'dvmem-all (Mb)', 'nbr linked-libs'])
129 for k,v in lib_stats.items():
130 o.writerow ([os.path.basename(k), v['vmem_self'], v['vmem_all'], v['nbr_linked']])
131
132 print (":: saving vmem statistics in [%s]... [done]"%fname)
133
134def main():
135
136 parser = argparse.ArgumentParser(
137 description='get the inclusive and exclusive vmem sizes of a library'
138 )
139 _add = parser.add_argument
140 _add('libnames',
141 type=str,
142 nargs='+',
143 help='list of library names to be inspected')
144 _add('--detailed',
145 action='store_true',
146 default=False,
147 help='enable detailed output')
148 args = parser.parse_args()
149
150 libnames = args.libnames
151 doDetailed = args.detailed
152
153 print (":: inspecting libraries: %s" % libnames)
154 display,lib_stats = analyze_libraries (libnames, doDetailed)
155
156 for l in display:
157 print (l)
158 save_stats (lib_stats)
159
160 return lib_stats
161
162if __name__ == '__main__':
163 lib_stats = main()
164
lib_loader(libname)
Definition vmem-sz.py:21
save_stats(lib_stats, fname=None)
Definition vmem-sz.py:119
load_lib(libname)
Definition vmem-sz.py:25
analyze(libname)
Definition vmem-sz.py:47
dep_libs(libname)
Definition vmem-sz.py:35
analyze_libraries(libnames, detailed=False)
Definition vmem-sz.py:89