ATLAS Offline Software
dso-stats.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 # @file: PyUtils/bin/dso-stats.py
6 # @purpose: compile statistics about shared libraries
7 # @author: Scott Snyder
8 
9 import re
10 import sys
11 import os
12 import subprocess
13 
14 def getstatus(cmd):
15  sc,_ = subprocess.getstatusoutput(cmd)
16  return sc
17 subprocess.getstatus = getstatus
18 del getstatus
19 
20 def getoutput(cmd):
21  _,out = subprocess.getstatusoutput(cmd)
22  return out
23 subprocess.getoutput = getoutput
24 del getoutput
25 
26 
27 #lib = 'atlas-work4/InstallArea/i686-slc4-gcc34-dbg/lib/libAthenaROOTAccess.so'
28 def _getpagesz():
29  import resource
30  sz = resource.getpagesize()
31  del resource
32  return sz
33 PAGESIZE = int(_getpagesz())
34 del _getpagesz
35 
36 
37 pat = re.compile (' *[0-9]* ([^ ]+) *([0-9a-f]+)')
38 
39 format = "%(name)-30s %(dso)5s %(code)5s %(puredata)5s %(cpp)5s %(initdata)5s %(bss)5s %(tbss)5s %(frag)5s %(total)6s"
40 
41 def parse_lib (lib):
42  out = subprocess.getoutput ("objdump -h " + lib)
43  secs = []
44  for l in out.split ('\n'):
45  m = pat.match (l)
46  if m:
47  secs.append ((m.group(1), int(m.group(2), 16)))
48  return secs
49 
50 
51 def _frag (sz):
52  return ((sz + PAGESIZE-1) & (~(PAGESIZE-1))) - sz
53 
54 
55 def _cleanname (name):
56  if name == 'None':
57  return 'None'
58  name = os.path.basename (name)
59  name = os.path.splitext(name)[0]
60  if name.startswith ('lib'):
61  name = name[3:]
62  return name
63 
64 
65 def _form (x):
66  return int ((x+512) / 1024)
67 
68 class Data:
69  def __init__ (self, secs = None, name = None):
70  self.name = name
71  self.dso = 0
72  self.code = 0
73  self.puredata = 0
74  self.cpp = 0
75  self.java = 0
76  self.initdata = 0
77  self.bss = 0
78  self.tbss = 0
79  self.frag = 0
80 
81  self.ro = 0
82  self.rw = 0
83 
84  if secs:
85  self.add_secs (secs)
86  self.est_frag()
87  return
88 
89 
90  def __iadd__ (self, other):
91  self.dso += other.dso
92  self.code += other.code
93  self.puredata += other.puredata
94  self.cpp += other.cpp
95  self.java += other.java
96  self.initdata += other.initdata
97  self.bss += other.bss
98  self.tbss += other.tbss
99  self.ro += other.ro
100  self.rw += other.rw
101  self.frag += other.frag
102  return self
103 
104 
105  def est_frag (self):
106  self.frag += _frag (self.ro)
107  self.frag += _frag (self.rw)
108  self.frag += _frag (self.bss)
109  self.frag += _frag (self.tbss)
110  return
111 
112 
113  def total (self):
114  return (self.dso + self.code + self.puredata + self.cpp +
115  self.java + self.initdata + self.frag + self.bss + self.tbss)
116 
117 
118  def add_secs (self, secs):
119  for s, sz in secs:
120  if s in ['.hash', '.dynsym', '.dynstr', '.gnu.version',
121  '.gnu.version_r', '.rel.dyn', '.rel.plt',
122  '.init', '.plt', '.fini', '.init_array', '.fini_array',
123  '.gnu.hash', '.rela.dyn', '.rela.plt',
124  '.data.rel.ro']:
125  self.dso += sz
126  self.ro += sz
127 
128  elif s in ['.text']:
129  self.code += sz
130  self.ro += sz
131 
132  elif s in ['.rodata']:
133  self.puredata += sz
134  self.ro += sz
135 
136  elif s in ['.eh_frame_hdr', '.eh_frame', '.gcc_except_table']:
137  self.cpp += sz
138  self.ro += sz
139 
140  elif s in ['.ctors', '.dtors']:
141  self.cpp += sz
142  self.rw += sz
143 
144 
145  elif s in ['.jcr']:
146  self.java += sz
147  self.rw += sz
148 
149  elif s in ['.dynamic', '.got', '.got.plt', '.plt.got']:
150  self.dso += sz
151  self.rw += sz
152 
153  elif s in ['.data']:
154  self.initdata += sz
155  self.rw += sz
156 
157  elif s in ['.bss']:
158  self.bss += sz
159 
160  elif s in ['.tbss']:
161  self.tbss += sz
162 
163  elif s in ['.comment', '.gnu_debuglink'] or s.startswith ('.debug'):
164  pass
165 
166  else:
167  print ('** Unknown section [%s] **' % s, file=sys.stderr)
168 
169  return
170 
171 
172 
173  def dump (self, f):
174  kw = {}
175  kw['name'] = _cleanname (self.name)
176  kw['dso'] = _form (self.dso)
177  kw['code'] = _form (self.code)
178  kw['puredata'] = _form (self.puredata)
179  kw['cpp'] = _form (self.cpp)
180  kw['java'] = _form (self.java)
181  kw['initdata'] = _form (self.initdata)
182  kw['frag'] = _form (self.frag)
183  kw['bss'] = _form (self.bss)
184  kw['tbss'] = _form (self.tbss)
185  kw['total'] = _form (self.total())
186  print (format % kw, file=f)
187 
188 def main():
189 
190  import optparse
191  parser = optparse.OptionParser(description="compile size statistics for shared libraries",
192  usage="%prog LIB [LIB...]")
193 
194  (opt, args) = parser.parse_args()
195  if len(args)==0:
196  parser.error("Invalid number of arguments specified")
197 
198  libs = []
199  total = Data(name = 'Total')
200  for lib in args:
201  secs = parse_lib(lib)
202  data = Data (secs, name = lib)
203  libs.append (data)
204  total += data
205  libs.sort (key = lambda x: x.total(), reverse=True)
206  kw = {'name' : 'Name',
207  'dso' : 'DSO',
208  'code' : 'Code',
209  'puredata': 'Pure',
210  'cpp' : 'C++',
211  'java' : 'Java',
212  'initdata': 'data',
213  'bss' : 'BSS',
214  'tbss' : 'TBSS',
215  'frag' : 'Frag',
216  'total': 'Total'}
217  print (format % kw, file=sys.stdout)
218  for l in libs:
219  l.dump (sys.stdout)
220  total.dump (sys.stdout)
221 
222  return 0
223 
224 
225 if __name__ == "__main__":
226  try:
227  sys.exit(main())
228  except KeyboardInterrupt:
229  sys.exit(1)
230 
dso-stats.Data.code
code
Definition: dso-stats.py:72
dso-stats.Data
Definition: dso-stats.py:68
dso-stats.Data.total
def total(self)
Definition: dso-stats.py:113
dso-stats.getoutput
def getoutput(cmd)
Definition: dso-stats.py:20
dso-stats.Data.__init__
def __init__(self, secs=None, name=None)
Definition: dso-stats.py:69
dso-stats.Data.est_frag
def est_frag(self)
Definition: dso-stats.py:105
dso-stats._form
def _form(x)
Definition: dso-stats.py:65
dso-stats.Data.initdata
initdata
Definition: dso-stats.py:76
dso-stats.Data.cpp
cpp
Definition: dso-stats.py:74
dso-stats.parse_lib
def parse_lib(lib)
Definition: dso-stats.py:41
dso-stats.Data.__iadd__
def __iadd__(self, other)
Definition: dso-stats.py:90
dso-stats._getpagesz
def _getpagesz()
Definition: dso-stats.py:28
dso-stats.Data.frag
frag
Definition: dso-stats.py:79
dso-stats.getstatus
def getstatus(cmd)
Definition: dso-stats.py:14
dso-stats.Data.dump
def dump(self, f)
Definition: dso-stats.py:173
dso-stats.Data.bss
bss
Definition: dso-stats.py:77
dso-stats.Data.add_secs
def add_secs(self, secs)
Definition: dso-stats.py:118
dso-stats.Data.java
java
Definition: dso-stats.py:75
dso-stats.Data.name
name
Definition: dso-stats.py:70
dso-stats.Data.puredata
puredata
Definition: dso-stats.py:73
dso-stats.Data.rw
rw
Definition: dso-stats.py:82
dso-stats._cleanname
def _cleanname(name)
Definition: dso-stats.py:55
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
dso-stats._frag
def _frag(sz)
Definition: dso-stats.py:51
dso-stats.main
def main()
Definition: dso-stats.py:188
dso-stats.Data.ro
ro
Definition: dso-stats.py:81
dso-stats.Data.dso
dso
Definition: dso-stats.py:71
dso-stats.Data.tbss
tbss
Definition: dso-stats.py:78