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

Side by Side Diff: tools/binary_size/map2size.py

Issue 2795593005: //tools/binary_size: Various enhancements to console.py (Closed)
Patch Set: Review fixes Created 3 years, 8 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/integration_test.py ('k') | tools/binary_size/match_util.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 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2017 The Chromium Authors. All rights reserved. 2 # Copyright 2017 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Main Python API for analyzing binary size.""" 6 """Main Python API for analyzing binary size."""
7 7
8 import argparse 8 import argparse
9 import datetime 9 import datetime
10 import distutils.spawn 10 import distutils.spawn
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 symbol.name = non_anonymous 88 symbol.name = non_anonymous
89 symbol.full_name = symbol.full_name.replace( 89 symbol.full_name = symbol.full_name.replace(
90 '(anonymous namespace)::', '') 90 '(anonymous namespace)::', '')
91 91
92 if symbol.section != 't' and '(' in symbol.name: 92 if symbol.section != 't' and '(' in symbol.name:
93 # Pretty rare. Example: 93 # Pretty rare. Example:
94 # blink::CSSValueKeywordsHash::findValueImpl(char const*)::value_word_list 94 # blink::CSSValueKeywordsHash::findValueImpl(char const*)::value_word_list
95 symbol.full_name = symbol.name 95 symbol.full_name = symbol.name
96 symbol.name = re.sub(r'\(.*\)', '', symbol.full_name) 96 symbol.name = re.sub(r'\(.*\)', '', symbol.full_name)
97 97
98 # Don't bother storing both if they are the same.
99 if symbol.full_name == symbol.name:
100 symbol.full_name = ''
101
98 logging.debug('Found name prefixes of: %r', found_prefixes) 102 logging.debug('Found name prefixes of: %r', found_prefixes)
99 103
100 104
101 def _NormalizeObjectPaths(symbol_group): 105 def _NormalizeObjectPaths(symbol_group):
102 """Ensures that all paths are formatted in a useful way.""" 106 """Ensures that all paths are formatted in a useful way."""
103 for symbol in symbol_group: 107 for symbol in symbol_group:
104 path = symbol.object_path 108 path = symbol.object_path
105 if path.startswith('obj/'): 109 if path.startswith('obj/'):
106 # Convert obj/third_party/... -> third_party/... 110 # Convert obj/third_party/... -> third_party/...
107 path = path[4:] 111 path = path[4:]
108 elif path.startswith('../../'): 112 elif path.startswith('../../'):
109 # Convert ../../third_party/... -> third_party/... 113 # Convert ../../third_party/... -> third_party/...
110 path = path[6:] 114 path = path[6:]
111 if path.endswith(')'): 115 if path.endswith(')'):
112 # Convert foo/bar.a(baz.o) -> foo/bar.a/(baz.o) 116 # Convert foo/bar.a(baz.o) -> foo/bar.a/baz.o
113 start_idx = path.index('(') 117 start_idx = path.index('(')
114 path = os.path.join(path[:start_idx], path[start_idx:]) 118 path = os.path.join(path[:start_idx], path[start_idx + 1:-1])
115 symbol.object_path = path 119 symbol.object_path = path
116 120
117 121
118 def _NormalizeSourcePath(path): 122 def _NormalizeSourcePath(path):
119 if path.startswith('gen/'): 123 if path.startswith('gen/'):
120 # Convert gen/third_party/... -> third_party/... 124 # Convert gen/third_party/... -> third_party/...
121 return path[4:] 125 return path[4:]
122 if path.startswith('../../'): 126 if path.startswith('../../'):
123 # Convert ../../third_party/... -> third_party/... 127 # Convert ../../third_party/... -> third_party/...
124 return path[6:] 128 return path[6:]
(...skipping 16 matching lines...) Expand all
141 else: 145 else:
142 logging.warning('Could not find source path for %s', object_path) 146 logging.warning('Could not find source path for %s', object_path)
143 logging.debug('Parsed %d .ninja files.', mapper.GetParsedFileCount()) 147 logging.debug('Parsed %d .ninja files.', mapper.GetParsedFileCount())
144 148
145 149
146 def _RemoveDuplicatesAndCalculatePadding(symbol_group): 150 def _RemoveDuplicatesAndCalculatePadding(symbol_group):
147 """Removes symbols at the same address and calculates the |padding| field. 151 """Removes symbols at the same address and calculates the |padding| field.
148 152
149 Symbols must already be sorted by |address|. 153 Symbols must already be sorted by |address|.
150 """ 154 """
151 to_remove = set() 155 to_remove = []
152 all_symbols = symbol_group.symbols 156 for i, symbol in enumerate(symbol_group[1:]):
153 for i, symbol in enumerate(all_symbols[1:]): 157 prev_symbol = symbol_group[i]
154 prev_symbol = all_symbols[i]
155 if prev_symbol.section_name != symbol.section_name: 158 if prev_symbol.section_name != symbol.section_name:
156 continue 159 continue
157 if symbol.address > 0 and prev_symbol.address > 0: 160 if symbol.address > 0 and prev_symbol.address > 0:
158 # Fold symbols that are at the same address (happens in nm output). 161 # Fold symbols that are at the same address (happens in nm output).
159 if symbol.address == prev_symbol.address: 162 if symbol.address == prev_symbol.address:
160 symbol.size = max(prev_symbol.size, symbol.size) 163 symbol.size = max(prev_symbol.size, symbol.size)
161 to_remove.add(i + 1) 164 to_remove.add(symbol)
162 continue 165 continue
163 # Even with symbols at the same address removed, overlaps can still 166 # Even with symbols at the same address removed, overlaps can still
164 # happen. In this case, padding will be negative (and this is fine). 167 # happen. In this case, padding will be negative (and this is fine).
165 padding = symbol.address - prev_symbol.end_address 168 padding = symbol.address - prev_symbol.end_address
166 # These thresholds were found by manually auditing arm32 Chrome. 169 # These thresholds were found by manually auditing arm32 Chrome.
167 # E.g.: Set them to 0 and see what warnings get logged. 170 # E.g.: Set them to 0 and see what warnings get logged.
168 # TODO(agrieve): See if these thresholds make sense for architectures 171 # TODO(agrieve): See if these thresholds make sense for architectures
169 # other than arm32. 172 # other than arm32.
170 if (symbol.section in 'rd' and padding >= 256 or 173 if (symbol.section in 'rd' and padding >= 256 or
171 symbol.section in 't' and padding >= 64): 174 symbol.section in 't' and padding >= 64):
172 # For nm data, this is caused by data that has no associated symbol. 175 # For nm data, this is caused by data that has no associated symbol.
173 # The linker map file lists them with no name, but with a file. 176 # The linker map file lists them with no name, but with a file.
174 # Example: 177 # Example:
175 # .data 0x02d42764 0x120 .../V8SharedWorkerGlobalScope.o 178 # .data 0x02d42764 0x120 .../V8SharedWorkerGlobalScope.o
176 # Where as most look like: 179 # Where as most look like:
177 # .data.MANGLED_NAME... 180 # .data.MANGLED_NAME...
178 logging.debug('Large padding of %d between:\n A) %r\n B) %r' % ( 181 logging.debug('Large padding of %d between:\n A) %r\n B) %r' % (
179 padding, prev_symbol, symbol)) 182 padding, prev_symbol, symbol))
180 continue 183 continue
181 symbol.padding = padding 184 symbol.padding = padding
182 symbol.size += padding 185 symbol.size += padding
183 assert symbol.size >= 0, 'Symbol has negative size: ' + ( 186 assert symbol.size >= 0, 'Symbol has negative size: ' + (
184 '%r\nprev symbol: %r' % (symbol, prev_symbol)) 187 '%r\nprev symbol: %r' % (symbol, prev_symbol))
185 # Map files have no overlaps, so worth special-casing the no-op case. 188 # Map files have no overlaps, so worth special-casing the no-op case.
186 if to_remove: 189 if to_remove:
187 logging.info('Removing %d overlapping symbols', len(to_remove)) 190 logging.info('Removing %d overlapping symbols', len(to_remove))
188 symbol_group.symbols = ( 191 symbol_group -= models.SymbolGroup(to_remove)
189 [s for i, s in enumerate(all_symbols) if i not in to_remove])
190 192
191 193
192 def AddOptions(parser): 194 def AddOptions(parser):
193 parser.add_argument('--tool-prefix', default='', 195 parser.add_argument('--tool-prefix', default='',
194 help='Path prefix for c++filt.') 196 help='Path prefix for c++filt.')
195 parser.add_argument('--output-directory', 197 parser.add_argument('--output-directory',
196 help='Path to the root build directory.') 198 help='Path to the root build directory.')
197 199
198 200
199 def _DetectToolPrefix(tool_prefix, input_file, output_directory=None): 201 def _DetectToolPrefix(tool_prefix, input_file, output_directory=None):
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 logging.info('Recording metadata: %s', 308 logging.info('Recording metadata: %s',
307 describe.DescribeSizeInfoMetadata(size_info)) 309 describe.DescribeSizeInfoMetadata(size_info))
308 logging.info('Saving result to %s', args.output_file) 310 logging.info('Saving result to %s', args.output_file)
309 file_format.SaveSizeInfo(size_info, args.output_file) 311 file_format.SaveSizeInfo(size_info, args.output_file)
310 312
311 logging.info('Done') 313 logging.info('Done')
312 314
313 315
314 if __name__ == '__main__': 316 if __name__ == '__main__':
315 sys.exit(main(sys.argv)) 317 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « tools/binary_size/integration_test.py ('k') | tools/binary_size/match_util.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698