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