ATLAS Offline Software
Loading...
Searching...
No Matches
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
9import re
10import sys
11import os
12import subprocess
13
14def getstatus(cmd):
15 sc,_ = subprocess.getstatusoutput(cmd)
16 return sc
17subprocess.getstatus = getstatus
18del getstatus
19
20def getoutput(cmd):
21 _,out = subprocess.getstatusoutput(cmd)
22 return out
23subprocess.getoutput = getoutput
24del getoutput
25
26
27#lib = 'atlas-work4/InstallArea/i686-slc4-gcc34-dbg/lib/libAthenaROOTAccess.so'
29 import resource
30 sz = resource.getpagesize()
31 del resource
32 return sz
33PAGESIZE = int(_getpagesz())
34del _getpagesz
35
36
37pat = re.compile (' *[0-9]* ([^ ]+) *([0-9a-f]+)')
38
39format = "%(name)-30s %(dso)5s %(code)5s %(puredata)5s %(cpp)5s %(initdata)5s %(bss)5s %(tbss)5s %(frag)5s %(total)6s"
40
41def 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
51def _frag (sz):
52 return ((sz + PAGESIZE-1) & (~(PAGESIZE-1))) - sz
53
54
55def _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
65def _form (x):
66 return int ((x+512) / 1024)
67
68class 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
188def 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
225if __name__ == "__main__":
226 try:
227 sys.exit(main())
228 except KeyboardInterrupt:
229 sys.exit(1)
230
add_secs(self, secs)
Definition dso-stats.py:118
__iadd__(self, other)
Definition dso-stats.py:90
__init__(self, secs=None, name=None)
Definition dso-stats.py:69
parse_lib(lib)
Definition dso-stats.py:41
_frag(sz)
Definition dso-stats.py:51
_cleanname(name)
Definition dso-stats.py:55
-event-from-file