| OLD | NEW |
| 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 yield ' {}: {:,} bytes ({:.1%})'.format(name, size, percent) | 61 yield ' {}: {:,} bytes ({:.1%})'.format(name, size, percent) |
| 62 | 62 |
| 63 if self.verbose: | 63 if self.verbose: |
| 64 yield '' | 64 yield '' |
| 65 yield 'Other section sizes:' | 65 yield 'Other section sizes:' |
| 66 section_names = sorted(k for k in section_sizes.iterkeys() | 66 section_names = sorted(k for k in section_sizes.iterkeys() |
| 67 if k not in section_names) | 67 if k not in section_names) |
| 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, single_line=False): |
| 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} pss={} padding={} size_without_padding={}{}'.format( | 78 yield '{}@{:<9s} pss={} padding={} size_without_padding={}{}'.format( |
| 79 sym.section, address, int(sym.pss), sym.padding, | 79 sym.section, address, int(sym.pss), sym.padding, |
| 80 sym.size_without_padding, 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 elif single_line: |
| 91 count_part = ' (count=%d)' % len(sym) if sym.IsGroup() else '' |
| 92 yield '{}@{:<9s} {:<7} {}{}'.format( |
| 93 sym.section, address, int(sym.pss), sym.name, count_part) |
| 90 else: | 94 else: |
| 91 yield '{}@{:<9s} {:<7} {}'.format( | 95 yield '{}@{:<9s} {:<7} {}'.format( |
| 92 sym.section, address, int(sym.pss), | 96 sym.section, address, int(sym.pss), |
| 93 sym.source_path or sym.object_path or '{no path}') | 97 sym.source_path or sym.object_path or '{no path}') |
| 94 if sym.name: | 98 if sym.name: |
| 95 count_part = ' (count=%d)' % len(sym) if sym.IsGroup() else '' | 99 count_part = ' (count=%d)' % len(sym) if sym.IsGroup() else '' |
| 96 yield ' {}{}'.format(sym.name, count_part) | 100 yield ' {}{}'.format(sym.name, count_part) |
| 97 | 101 |
| 98 def _DescribeSymbolGroupChildren(self, group, indent=0): | 102 def _DescribeSymbolGroupChildren(self, group, indent=0): |
| 99 running_total = 0 | 103 running_total = 0 |
| 100 sorted_syms = group if group.is_sorted else group.Sorted() | 104 running_percent = 0 |
| 101 is_diff = isinstance(group, models.SymbolDiff) | 105 is_diff = isinstance(group, models.SymbolDiff) |
| 106 all_groups = all(s.IsGroup() for s in group) |
| 102 | 107 |
| 103 indent_prefix = '> ' * indent | 108 indent_prefix = '> ' * indent |
| 104 diff_prefix = '' | 109 diff_prefix = '' |
| 105 for s in sorted_syms: | 110 total = group.pss |
| 111 for index, s in enumerate(group): |
| 106 if group.IsBss() or not s.IsBss(): | 112 if group.IsBss() or not s.IsBss(): |
| 107 running_total += s.pss | 113 running_total += s.pss |
| 108 for l in self._DescribeSymbol(s): | 114 running_percent = running_total / total |
| 115 for l in self._DescribeSymbol(s, single_line=all_groups): |
| 109 if l[:4].isspace(): | 116 if l[:4].isspace(): |
| 110 indent_size = 8 + len(indent_prefix) + len(diff_prefix) | 117 indent_size = 8 + len(indent_prefix) + len(diff_prefix) |
| 111 yield '{} {}'.format(' ' * indent_size, l) | 118 yield '{} {}'.format(' ' * indent_size, l) |
| 112 else: | 119 else: |
| 113 if is_diff: | 120 if is_diff: |
| 114 diff_prefix = _DiffPrefix(group, s) | 121 diff_prefix = _DiffPrefix(group, s) |
| 115 yield '{}{}{:8} {}'.format(indent_prefix, diff_prefix, | 122 yield '{}{}{:<4} {:8} {:7} {}'.format( |
| 116 int(running_total), l) | 123 indent_prefix, diff_prefix, str(index) + ')', int(running_total), |
| 124 '({:.1%})'.format(running_percent), l) |
| 117 | 125 |
| 118 if self.recursive and s.IsGroup(): | 126 if self.recursive and s.IsGroup(): |
| 119 for l in self._DescribeSymbolGroupChildren(s, indent=indent + 1): | 127 for l in self._DescribeSymbolGroupChildren(s, indent=indent + 1): |
| 120 yield l | 128 yield l |
| 121 | 129 |
| 122 def _DescribeSymbolGroup(self, group): | 130 def _DescribeSymbolGroup(self, group): |
| 123 total_size = group.pss | 131 total_size = group.pss |
| 124 code_syms = group.WhereInSection('t') | 132 code_syms = group.WhereInSection('t') |
| 125 code_size = code_syms.pss | 133 code_size = code_syms.pss |
| 126 ro_size = code_syms.Inverted().WhereInSection('r').pss | 134 ro_size = code_syms.Inverted().WhereInSection('r').pss |
| 127 unique_paths = set(s.object_path for s in group) | 135 unique_paths = set(s.object_path for s in group) |
| 128 header_desc = [ | 136 header_desc = [ |
| 129 'Showing {:,} symbols ({:,} unique) with total pss: {} bytes'.format( | 137 'Showing {:,} symbols ({:,} unique) with total pss: {} bytes'.format( |
| 130 len(group), group.CountUniqueSymbols(), int(total_size)), | 138 len(group), group.CountUniqueSymbols(), int(total_size)), |
| 131 '.text={:<10} .rodata={:<10} other={:<10} total={}'.format( | 139 '.text={:<10} .rodata={:<10} other={:<10} total={}'.format( |
| 132 _PrettySize(int(code_size)), _PrettySize(int(ro_size)), | 140 _PrettySize(int(code_size)), _PrettySize(int(ro_size)), |
| 133 _PrettySize(int(total_size - code_size - ro_size)), | 141 _PrettySize(int(total_size - code_size - ro_size)), |
| 134 _PrettySize(int(total_size))), | 142 _PrettySize(int(total_size))), |
| 135 'Number of object files: {}'.format(len(unique_paths)), | 143 'Number of object files: {}'.format(len(unique_paths)), |
| 136 '', | 144 '', |
| 137 'First columns are: running total, address, pss', | 145 'Index, Running Total, Section@Address, PSS', |
| 146 '-' * 60 |
| 138 ] | 147 ] |
| 139 children_desc = self._DescribeSymbolGroupChildren(group) | 148 children_desc = self._DescribeSymbolGroupChildren(group) |
| 140 return itertools.chain(header_desc, children_desc) | 149 return itertools.chain(header_desc, children_desc) |
| 141 | 150 |
| 142 def _DescribeSymbolDiff(self, diff): | 151 def _DescribeSymbolDiff(self, diff): |
| 143 header_template = ('{} symbols added (+), {} changed (~), {} removed (-), ' | 152 header_template = ('{} symbols added (+), {} changed (~), {} removed (-), ' |
| 144 '{} unchanged ({})') | 153 '{} unchanged ({})') |
| 145 unchanged_msg = '=' if self.verbose else 'not shown' | 154 unchanged_msg = '=' if self.verbose else 'not shown' |
| 146 symbol_delta_desc = [header_template.format( | 155 symbol_delta_desc = [header_template.format( |
| 147 diff.added_count, diff.changed_count, diff.removed_count, | 156 diff.added_count, diff.changed_count, diff.removed_count, |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 | 300 |
| 292 def GenerateLines(obj, verbose=False, recursive=False): | 301 def GenerateLines(obj, verbose=False, recursive=False): |
| 293 """Returns an iterable of lines (without \n) that describes |obj|.""" | 302 """Returns an iterable of lines (without \n) that describes |obj|.""" |
| 294 return Describer(verbose=verbose, recursive=recursive).GenerateLines(obj) | 303 return Describer(verbose=verbose, recursive=recursive).GenerateLines(obj) |
| 295 | 304 |
| 296 | 305 |
| 297 def WriteLines(lines, func): | 306 def WriteLines(lines, func): |
| 298 for l in lines: | 307 for l in lines: |
| 299 func(l) | 308 func(l) |
| 300 func('\n') | 309 func('\n') |
| OLD | NEW |