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 | 4 |
5 """An interactive console for looking analyzing .size files.""" | 5 """An interactive console for looking analyzing .size files.""" |
6 | 6 |
7 import argparse | 7 import argparse |
8 import atexit | 8 import atexit |
9 import code | 9 import code |
10 import contextlib | 10 import contextlib |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 self._size_infos = size_infos | 81 self._size_infos = size_infos |
82 self._size_paths = size_paths | 82 self._size_paths = size_paths |
83 self._disassemble_prefix_len = None | 83 self._disassemble_prefix_len = None |
84 | 84 |
85 if len(size_infos) == 1: | 85 if len(size_infos) == 1: |
86 self._variables['size_info'] = size_infos[0] | 86 self._variables['size_info'] = size_infos[0] |
87 else: | 87 else: |
88 for i, size_info in enumerate(size_infos): | 88 for i, size_info in enumerate(size_infos): |
89 self._variables['size_info%d' % (i + 1)] = size_info | 89 self._variables['size_info%d' % (i + 1)] = size_info |
90 | 90 |
91 def _DiffFunc(self, before=None, after=None, cluster=True, sort=True): | 91 def _DiffFunc(self, before=None, after=None, sort=True): |
92 """Diffs two SizeInfo objects. Returns a SizeInfoDiff. | 92 """Diffs two SizeInfo objects. Returns a SizeInfoDiff. |
93 | 93 |
94 Args: | 94 Args: |
95 before: Defaults to first size_infos[0]. | 95 before: Defaults to first size_infos[0]. |
96 after: Defaults to second size_infos[1]. | 96 after: Defaults to second size_infos[1]. |
97 cluster: When True (default), calls SymbolGroup.Clustered() after diffing. | |
98 Generally reduces noise. | |
99 sort: When True (default), calls SymbolGroup.Sorted() after diffing. | 97 sort: When True (default), calls SymbolGroup.Sorted() after diffing. |
100 """ | 98 """ |
101 before = before if before is not None else self._size_infos[0] | 99 before = before if before is not None else self._size_infos[0] |
102 after = after if after is not None else self._size_infos[1] | 100 after = after if after is not None else self._size_infos[1] |
103 ret = diff.Diff(before, after) | 101 ret = diff.Diff(before, after) |
104 if cluster: | |
105 ret.symbols = ret.symbols.Clustered() | |
106 if sort: | 102 if sort: |
107 ret.symbols = ret.symbols.Sorted() | 103 ret.symbols = ret.symbols.Sorted() |
108 return ret | 104 return ret |
109 | 105 |
110 def _PrintFunc(self, obj=None, verbose=False, recursive=False, use_pager=None, | 106 def _PrintFunc(self, obj=None, verbose=False, recursive=False, use_pager=None, |
111 to_file=None): | 107 to_file=None): |
112 """Prints out the given Symbol / SymbolGroup / SymbolDiff / SizeInfo. | 108 """Prints out the given Symbol / SymbolGroup / SymbolDiff / SizeInfo. |
113 | 109 |
114 For convenience, |obj| will be appended to the global "printed" list. | 110 For convenience, |obj| will be appended to the global "printed" list. |
115 | 111 |
116 Args: | 112 Args: |
117 obj: The object to be printed. Defaults to size_infos[-1]. | 113 obj: The object to be printed. Defaults to size_infos[-1]. |
118 verbose: Show more detailed output. | 114 verbose: Show more detailed output. |
119 recursive: Print children of nested SymbolGroups. | 115 recursive: Print children of nested SymbolGroups. |
120 use_pager: Pipe output through `less`. Ignored when |obj| is a Symbol. | 116 use_pager: Pipe output through `less`. Ignored when |obj| is a Symbol. |
121 default is to automatically pipe when output is long. | 117 default is to automatically pipe when output is long. |
122 to_file: Rather than print to stdio, write to the given file. | 118 to_file: Rather than print to stdio, write to the given file. |
123 """ | 119 """ |
124 if not self._printed_variables or self._printed_variables[-1] != obj: | 120 if not self._printed_variables or self._printed_variables[-1] != obj: |
125 self._printed_variables.append(obj) | 121 self._printed_variables.append(obj) |
126 obj = obj if obj is not None else self._size_infos[-1] | 122 obj = obj if obj is not None else self._size_infos[-1] |
127 lines = describe.GenerateLines(obj, verbose=verbose, recursive=recursive) | 123 lines = describe.GenerateLines(obj, verbose=verbose, recursive=recursive) |
128 _WriteToStream(lines, use_pager=use_pager, to_file=to_file) | 124 _WriteToStream(lines, use_pager=use_pager, to_file=to_file) |
129 | 125 |
130 def _ElfPathAndToolPrefixForSymbol(self, symbol, elf_path, tool_prefix): | 126 def _ElfPathAndToolPrefixForSymbol(self, symbol, elf_path, tool_prefix): |
131 size_info = None | 127 size_info = None |
132 size_path = None | 128 size_path = None |
133 for size_info, size_path in zip(self._size_infos, self._size_paths): | 129 for size_info, size_path in zip(self._size_infos, self._size_paths): |
134 if symbol in size_info.symbols: | 130 if symbol in size_info.raw_symbols: |
135 break | 131 break |
136 else: | 132 else: |
137 # If symbols is from a diff(), use its address+name to find it. | 133 # If symbols is from a diff(), use its address+name to find it. |
138 for size_info, size_path in zip(self._size_infos, self._size_paths): | 134 for size_info, size_path in zip(self._size_infos, self._size_paths): |
139 matched = size_info.symbols.WhereAddressInRange(symbol.address) | 135 matched = size_info.raw_symbols.WhereAddressInRange(symbol.address) |
140 # Use last matched symbol to skip over padding-only symbols. | 136 # Use last matched symbol to skip over padding-only symbols. |
141 if len(matched) > 0 and matched[-1].full_name == symbol.full_name: | 137 if len(matched) > 0 and matched[-1].full_name == symbol.full_name: |
142 symbol = matched[-1] | 138 symbol = matched[-1] |
143 break | 139 break |
144 else: | 140 else: |
145 assert False, 'Symbol does not belong to a size_info.' | 141 assert False, 'Symbol does not belong to a size_info.' |
146 | 142 |
147 orig_tool_prefix = size_info.metadata.get(models.METADATA_TOOL_PREFIX) | 143 orig_tool_prefix = size_info.metadata.get(models.METADATA_TOOL_PREFIX) |
148 if orig_tool_prefix: | 144 if orig_tool_prefix: |
149 orig_tool_prefix = paths.FromSrcRootRelative(orig_tool_prefix) | 145 orig_tool_prefix = paths.FromSrcRootRelative(orig_tool_prefix) |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 '# Note: Use "help(ExpandRegex)" for more about what {{_print_}} does.', | 260 '# Note: Use "help(ExpandRegex)" for more about what {{_print_}} does.', |
265 'print_syms = size_info.symbols.WhereMatches(r"{{_print_}}")', | 261 'print_syms = size_info.symbols.WhereMatches(r"{{_print_}}")', |
266 'Print(print_syms - print_syms.WherePathMatches(r"^components/"))', | 262 'Print(print_syms - print_syms.WherePathMatches(r"^components/"))', |
267 '', | 263 '', |
268 '# Diff two .size files and save result to a file:', | 264 '# Diff two .size files and save result to a file:', |
269 'Print(Diff(size_info1, size_info2), to_file="output.txt")', | 265 'Print(Diff(size_info1, size_info2), to_file="output.txt")', |
270 '', | 266 '', |
271 '# View per-component breakdowns, then drill into the last entry.', | 267 '# View per-component breakdowns, then drill into the last entry.', |
272 'c = canned_queries.CategorizeByChromeComponent()', | 268 'c = canned_queries.CategorizeByChromeComponent()', |
273 'Print(c)', | 269 'Print(c)', |
274 'Print(c[-1].GroupedByPath(depth=2).Clustered().Sorted())', | 270 'Print(c[-1].GroupedByPath(depth=2).Sorted())', |
275 '', | 271 '', |
276 '# For even more inspiration, look at canned_queries.py', | 272 '# For even more inspiration, look at canned_queries.py', |
277 '# (and feel free to add your own!).', | 273 '# (and feel free to add your own!).', |
278 ]) | 274 ]) |
279 | 275 |
280 def _CreateBanner(self): | 276 def _CreateBanner(self): |
281 symbol_info_keys = sorted(m for m in dir(models.SizeInfo) if m[0] != '_') | 277 symbol_info_keys = sorted(m for m in dir(models.SizeInfo) if m[0] != '_') |
282 symbol_keys = sorted(m for m in dir(models.Symbol) if m[0] != '_') | 278 symbol_keys = sorted(m for m in dir(models.Symbol) if m[0] != '_') |
283 symbol_group_keys = [m for m in dir(models.SymbolGroup) if m[0] != '_'] | 279 symbol_group_keys = [m for m in dir(models.SymbolGroup) if m[0] != '_'] |
284 symbol_diff_keys = sorted(m for m in dir(models.SymbolDiff) | 280 symbol_diff_keys = sorted(m for m in dir(models.SymbolDiff) |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 output_directory=args.output_directory, | 351 output_directory=args.output_directory, |
356 any_path_within_output_directory=args.inputs[0]) | 352 any_path_within_output_directory=args.inputs[0]) |
357 session = _Session(size_infos, args.inputs, lazy_paths) | 353 session = _Session(size_infos, args.inputs, lazy_paths) |
358 | 354 |
359 if args.query: | 355 if args.query: |
360 logging.info('Running query from command-line.') | 356 logging.info('Running query from command-line.') |
361 session.Eval(args.query) | 357 session.Eval(args.query) |
362 else: | 358 else: |
363 logging.info('Entering interactive console.') | 359 logging.info('Entering interactive console.') |
364 session.GoInteractive() | 360 session.GoInteractive() |
OLD | NEW |