Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: tools/binary_size/libsupersize/describe.py

Issue 2851473003: supersize: Track symbol aliases and shared symbols (Closed)
Patch Set: fix regression in calculate padding introduced in ps3 Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/binary_size/libsupersize/console.py ('k') | tools/binary_size/libsupersize/diff.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2017 The Chromium Authors. All rights reserved. 1 # Copyright 2017 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 """Methods for converting model objects to human-readable formats.""" 4 """Methods for converting model objects to human-readable formats."""
5 5
6 import datetime 6 import datetime
7 import itertools 7 import itertools
8 import time 8 import time
9 9
10 import models 10 import models
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 for name in section_names: 68 for name in section_names:
69 yield ' {}: {:,} bytes'.format(name, section_sizes[name]) 69 yield ' {}: {:,} bytes'.format(name, section_sizes[name])
70 70
71 def _DescribeSymbol(self, sym): 71 def _DescribeSymbol(self, sym):
72 if sym.IsGroup(): 72 if sym.IsGroup():
73 address = 'Group' 73 address = 'Group'
74 else: 74 else:
75 address = hex(sym.address) 75 address = hex(sym.address)
76 if self.verbose: 76 if self.verbose:
77 count_part = ' count=%d' % len(sym) if sym.IsGroup() else '' 77 count_part = ' count=%d' % len(sym) if sym.IsGroup() else ''
78 yield '{}@{:<9s} size={} padding={} size_without_padding={}{}'.format( 78 yield '{}@{:<9s} pss={} padding={} size_without_padding={}{}'.format(
79 sym.section, address, sym.size, sym.padding, sym.size_without_padding, 79 sym.section, address, int(sym.pss), sym.padding,
80 count_part) 80 sym.size_without_padding, count_part)
81 yield ' source_path={} \tobject_path={}'.format( 81 yield ' source_path={} \tobject_path={}'.format(
82 sym.source_path, sym.object_path) 82 sym.source_path, sym.object_path)
83 if sym.name: 83 if sym.name:
84 yield ' flags={} name={}'.format(sym.FlagsString(), sym.name) 84 yield ' flags={} name={}'.format(sym.FlagsString(), sym.name)
85 if sym.full_name: 85 if sym.full_name:
86 yield ' full_name={}'.format(sym.full_name) 86 yield ' full_name={}'.format(sym.full_name)
87 elif sym.full_name: 87 elif sym.full_name:
88 yield ' flags={} full_name={}'.format( 88 yield ' flags={} full_name={}'.format(
89 sym.FlagsString(), sym.full_name) 89 sym.FlagsString(), sym.full_name)
90 else: 90 else:
91 yield '{}@{:<9s} {:<7} {}'.format( 91 yield '{}@{:<9s} {:<7} {}'.format(
92 sym.section, address, sym.size, 92 sym.section, address, int(sym.pss),
93 sym.source_path or sym.object_path or '{no path}') 93 sym.source_path or sym.object_path or '{no path}')
94 if sym.name: 94 if sym.name:
95 count_part = ' (count=%d)' % len(sym) if sym.IsGroup() else '' 95 count_part = ' (count=%d)' % len(sym) if sym.IsGroup() else ''
96 yield ' {}{}'.format(sym.name, count_part) 96 yield ' {}{}'.format(sym.name, count_part)
97 97
98 def _DescribeSymbolGroupChildren(self, group, indent=0): 98 def _DescribeSymbolGroupChildren(self, group, indent=0):
99 running_total = 0 99 running_total = 0
100 sorted_syms = group if group.is_sorted else group.Sorted() 100 sorted_syms = group if group.is_sorted else group.Sorted()
101 is_diff = isinstance(group, models.SymbolDiff) 101 is_diff = isinstance(group, models.SymbolDiff)
102 102
103 indent_prefix = '> ' * indent 103 indent_prefix = '> ' * indent
104 diff_prefix = '' 104 diff_prefix = ''
105 for s in sorted_syms: 105 for s in sorted_syms:
106 if group.IsBss() or not s.IsBss(): 106 if group.IsBss() or not s.IsBss():
107 running_total += s.size 107 running_total += s.pss
108 for l in self._DescribeSymbol(s): 108 for l in self._DescribeSymbol(s):
109 if l[:4].isspace(): 109 if l[:4].isspace():
110 indent_size = 8 + len(indent_prefix) + len(diff_prefix) 110 indent_size = 8 + len(indent_prefix) + len(diff_prefix)
111 yield '{} {}'.format(' ' * indent_size, l) 111 yield '{} {}'.format(' ' * indent_size, l)
112 else: 112 else:
113 if is_diff: 113 if is_diff:
114 diff_prefix = _DiffPrefix(group, s) 114 diff_prefix = _DiffPrefix(group, s)
115 yield '{}{}{:8} {}'.format(indent_prefix, diff_prefix, 115 yield '{}{}{:8} {}'.format(indent_prefix, diff_prefix,
116 running_total, l) 116 int(running_total), l)
117 117
118 if self.recursive and s.IsGroup(): 118 if self.recursive and s.IsGroup():
119 for l in self._DescribeSymbolGroupChildren(s, indent=indent + 1): 119 for l in self._DescribeSymbolGroupChildren(s, indent=indent + 1):
120 yield l 120 yield l
121 121
122 def _DescribeSymbolGroup(self, group): 122 def _DescribeSymbolGroup(self, group):
123 total_size = group.size 123 total_size = group.pss
124 code_syms = group.WhereInSection('t') 124 code_syms = group.WhereInSection('t')
125 code_size = code_syms.size 125 code_size = code_syms.pss
126 ro_size = code_syms.Inverted().WhereInSection('r').size 126 ro_size = code_syms.Inverted().WhereInSection('r').pss
127 unique_paths = set(s.object_path for s in group) 127 unique_paths = set(s.object_path for s in group)
128 header_desc = [ 128 header_desc = [
129 'Showing {:,} symbols with total size: {} bytes'.format( 129 'Showing {:,} symbols with total pss: {} bytes'.format(
130 len(group), total_size), 130 len(group), int(total_size)),
131 '.text={:<10} .rodata={:<10} other={:<10} total={}'.format( 131 '.text={:<10} .rodata={:<10} other={:<10} total={}'.format(
132 _PrettySize(code_size), _PrettySize(ro_size), 132 _PrettySize(int(code_size)), _PrettySize(int(ro_size)),
133 _PrettySize(total_size - code_size - ro_size), 133 _PrettySize(int(total_size - code_size - ro_size)),
134 _PrettySize(total_size)), 134 _PrettySize(int(total_size))),
135 'Number of object files: {}'.format(len(unique_paths)), 135 'Number of object files: {}'.format(len(unique_paths)),
136 '', 136 '',
137 'First columns are: running total, type, size', 137 'First columns are: running total, address, pss',
138 ] 138 ]
139 children_desc = self._DescribeSymbolGroupChildren(group) 139 children_desc = self._DescribeSymbolGroupChildren(group)
140 return itertools.chain(header_desc, children_desc) 140 return itertools.chain(header_desc, children_desc)
141 141
142 def _DescribeSymbolDiff(self, diff): 142 def _DescribeSymbolDiff(self, diff):
143 header_template = ('{} symbols added (+), {} changed (~), {} removed (-), ' 143 header_template = ('{} symbols added (+), {} changed (~), {} removed (-), '
144 '{} unchanged ({})') 144 '{} unchanged ({})')
145 unchanged_msg = '=' if self.verbose else 'not shown' 145 unchanged_msg = '=' if self.verbose else 'not shown'
146 symbol_delta_desc = [header_template.format( 146 symbol_delta_desc = [header_template.format(
147 diff.added_count, diff.changed_count, diff.removed_count, 147 diff.added_count, diff.changed_count, diff.removed_count,
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 symbols = models.SymbolGroup(size_info.raw_symbols) 223 symbols = models.SymbolGroup(size_info.raw_symbols)
224 for section in models.SECTION_TO_SECTION_NAME: 224 for section in models.SECTION_TO_SECTION_NAME:
225 if section == 'd': 225 if section == 'd':
226 expected_size = sum(v for k, v in size_info.section_sizes.iteritems() 226 expected_size = sum(v for k, v in size_info.section_sizes.iteritems()
227 if k.startswith('.data')) 227 if k.startswith('.data'))
228 else: 228 else:
229 expected_size = size_info.section_sizes[ 229 expected_size = size_info.section_sizes[
230 models.SECTION_TO_SECTION_NAME[section]] 230 models.SECTION_TO_SECTION_NAME[section]]
231 231
232 def one_stat(group): 232 def one_stat(group):
233 template = ('Section %s has %.1f%% of %d bytes accounted for from ' 233 template = ('Section {}: has {:.1%} of {} bytes accounted for from '
234 '%d symbols. %d bytes are unaccounted for. Padding ' 234 '{} symbols. {} bytes are unaccounted for.')
235 'accounts for %d bytes')
236 actual_size = group.size 235 actual_size = group.size
237 count = len(group) 236 size_percent = float(actual_size) / expected_size
238 padding = group.padding 237 return template.format(section, size_percent, actual_size, len(group),
239 size_percent = 100.0 * actual_size / expected_size 238 expected_size - actual_size)
240 return (template % (section, size_percent, actual_size, count,
241 expected_size - actual_size, padding))
242 239
243 in_section = symbols.WhereInSection(section) 240 in_section = symbols.WhereInSection(section)
244 yield one_stat(in_section) 241 yield one_stat(in_section)
242 yield '* Padding accounts for {} bytes ({:.1%})'.format(
243 in_section.padding, float(in_section.padding) / in_section.size)
244
245 aliased_symbols = in_section.Filter(lambda s: s.aliases)
246 if len(aliased_symbols):
247 uniques = sum(1 for s in aliased_symbols.IterUniqueSymbols())
248 yield '* Contains {} aliases, mapped to {} addresses ({} bytes)'.format(
249 len(aliased_symbols), uniques, aliased_symbols.size)
250 else:
251 yield '* Contains 0 aliases'
252
253 inlined_symbols = in_section.WhereObjectPathMatches('{shared}')
254 if len(inlined_symbols):
255 yield '* {} symbols have shared ownership ({} bytes)'.format(
256 len(inlined_symbols), inlined_symbols.size)
257 else:
258 yield '* 0 symbols have shared ownership'
245 259
246 star_syms = in_section.WhereNameMatches(r'^\*') 260 star_syms = in_section.WhereNameMatches(r'^\*')
247 attributed_syms = star_syms.Inverted().WhereHasAnyAttribution() 261 attributed_syms = star_syms.Inverted().WhereHasAnyAttribution()
248 anonymous_syms = attributed_syms.Inverted() 262 anonymous_syms = attributed_syms.Inverted()
249 if star_syms or anonymous_syms: 263 if star_syms or anonymous_syms:
250 missing_size = star_syms.size + anonymous_syms.size 264 missing_size = star_syms.pss + anonymous_syms.pss
251 yield ('+ Without %d merge sections and %d anonymous entries (' 265 anon_str = ''
252 'accounting for %d bytes):') % ( 266 if len(anonymous_syms):
253 len(star_syms), len(anonymous_syms), missing_size) 267 anon_str = 'and {} anonymous entries '.format(len(anonymous_syms))
254 yield '+ ' + one_stat(attributed_syms) 268 yield '* Without {} merge sections {}(accounting for {} bytes):'.format(
269 len(star_syms), anon_str, int(missing_size))
270 yield ' * ' + one_stat(attributed_syms)
255 271
256 272
257 def _UtcToLocal(utc): 273 def _UtcToLocal(utc):
258 epoch = time.mktime(utc.timetuple()) 274 epoch = time.mktime(utc.timetuple())
259 offset = (datetime.datetime.fromtimestamp(epoch) - 275 offset = (datetime.datetime.fromtimestamp(epoch) -
260 datetime.datetime.utcfromtimestamp(epoch)) 276 datetime.datetime.utcfromtimestamp(epoch))
261 return utc + offset 277 return utc + offset
262 278
263 279
264 def DescribeMetadata(metadata): 280 def DescribeMetadata(metadata):
265 display_dict = metadata.copy() 281 display_dict = metadata.copy()
266 timestamp = display_dict.get(models.METADATA_ELF_MTIME) 282 timestamp = display_dict.get(models.METADATA_ELF_MTIME)
267 if timestamp: 283 if timestamp:
268 timestamp_obj = datetime.datetime.utcfromtimestamp(timestamp) 284 timestamp_obj = datetime.datetime.utcfromtimestamp(timestamp)
269 display_dict[models.METADATA_ELF_MTIME] = ( 285 display_dict[models.METADATA_ELF_MTIME] = (
270 _UtcToLocal(timestamp_obj).strftime('%Y-%m-%d %H:%M:%S')) 286 _UtcToLocal(timestamp_obj).strftime('%Y-%m-%d %H:%M:%S'))
271 gn_args = display_dict.get(models.METADATA_GN_ARGS) 287 gn_args = display_dict.get(models.METADATA_GN_ARGS)
272 if gn_args: 288 if gn_args:
273 display_dict[models.METADATA_GN_ARGS] = '; '.join(gn_args) 289 display_dict[models.METADATA_GN_ARGS] = ' '.join(gn_args)
274 return sorted('%s=%s' % t for t in display_dict.iteritems()) 290 return sorted('%s=%s' % t for t in display_dict.iteritems())
275 291
276 292
277 def GenerateLines(obj, verbose=False, recursive=False): 293 def GenerateLines(obj, verbose=False, recursive=False):
278 """Returns an iterable of lines (without \n) that describes |obj|.""" 294 """Returns an iterable of lines (without \n) that describes |obj|."""
279 return Describer(verbose=verbose, recursive=recursive).GenerateLines(obj) 295 return Describer(verbose=verbose, recursive=recursive).GenerateLines(obj)
280 296
281 297
282 def WriteLines(lines, func): 298 def WriteLines(lines, func):
283 for l in lines: 299 for l in lines:
284 func(l) 300 func(l)
285 func('\n') 301 func('\n')
OLDNEW
« no previous file with comments | « tools/binary_size/libsupersize/console.py ('k') | tools/binary_size/libsupersize/diff.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698