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 |