OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 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 """Describe the size difference of two binaries. | 6 """Describe the size difference of two binaries. |
7 | 7 |
8 Generates a description of the size difference of two binaries based | 8 Generates a description of the size difference of two binaries based |
9 on the difference of the size of various symbols. | 9 on the difference of the size of various symbols. |
10 | 10 |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 | 100 |
101 # We have now analyzed all symbols that are in cache1 and removed all of | 101 # We have now analyzed all symbols that are in cache1 and removed all of |
102 # the encountered symbols from cache2. What's left in cache2 is the new | 102 # the encountered symbols from cache2. What's left in cache2 is the new |
103 # symbols. | 103 # symbols. |
104 for key, bucket2 in cache2.iteritems(): | 104 for key, bucket2 in cache2.iteritems(): |
105 for symbol_name, symbol_size in bucket2.items(): | 105 for symbol_name, symbol_size in bucket2.items(): |
106 added.append((key[0], key[1], symbol_name, None, symbol_size)) | 106 added.append((key[0], key[1], symbol_name, None, symbol_size)) |
107 return (added, removed, changed, unchanged) | 107 return (added, removed, changed, unchanged) |
108 | 108 |
109 | 109 |
110 def TestCompare(): | |
111 # List entries have form: symbol_name, symbol_type, symbol_size, file_path | |
112 symbol_list1 = ( | |
113 # File with one symbol, left as-is. | |
114 ( 'unchanged', 't', 1000, '/file_unchanged' ), | |
115 # File with one symbol, changed. | |
116 ( 'changed', 't', 1000, '/file_all_changed' ), | |
117 # File with one symbol, deleted. | |
118 ( 'removed', 't', 1000, '/file_all_deleted' ), | |
119 # File with two symbols, one unchanged, one changed, same bucket | |
120 ( 'unchanged', 't', 1000, '/file_pair_unchanged_changed' ), | |
121 ( 'changed', 't', 1000, '/file_pair_unchanged_changed' ), | |
122 # File with two symbols, one unchanged, one deleted, same bucket | |
123 ( 'unchanged', 't', 1000, '/file_pair_unchanged_removed' ), | |
124 ( 'removed', 't', 1000, '/file_pair_unchanged_removed' ), | |
125 # File with two symbols, one unchanged, one added, same bucket | |
126 ( 'unchanged', 't', 1000, '/file_pair_unchanged_added' ), | |
127 # File with two symbols, one unchanged, one changed, different bucket | |
128 ( 'unchanged', 't', 1000, '/file_pair_unchanged_diffbuck_changed' ), | |
129 ( 'changed', '@', 1000, '/file_pair_unchanged_diffbuck_changed' ), | |
130 # File with two symbols, one unchanged, one deleted, different bucket | |
131 ( 'unchanged', 't', 1000, '/file_pair_unchanged_diffbuck_removed' ), | |
132 ( 'removed', '@', 1000, '/file_pair_unchanged_diffbuck_removed' ), | |
133 # File with two symbols, one unchanged, one added, different bucket | |
134 ( 'unchanged', 't', 1000, '/file_pair_unchanged_diffbuck_added' ), | |
135 # File with four symbols, one added, one removed, one changed, one unchanged | |
136 ( 'size_changed', 't', 1000, '/file_tetra' ), | |
137 ( 'removed', 't', 1000, '/file_tetra' ), | |
138 ( 'unchanged', 't', 1000, '/file_tetra' ), | |
139 ) | |
140 | |
141 symbol_list2 = ( | |
142 # File with one symbol, left as-is. | |
143 ( 'unchanged', 't', 1000, '/file_unchanged' ), | |
144 # File with one symbol, changed. | |
145 ( 'changed', 't', 2000, '/file_all_changed' ), | |
146 # File with two symbols, one unchanged, one changed, same bucket | |
147 ( 'unchanged', 't', 1000, '/file_pair_unchanged_changed' ), | |
148 ( 'changed', 't', 2000, '/file_pair_unchanged_changed' ), | |
149 # File with two symbols, one unchanged, one deleted, same bucket | |
150 ( 'unchanged', 't', 1000, '/file_pair_unchanged_removed' ), | |
151 # File with two symbols, one unchanged, one added, same bucket | |
152 ( 'unchanged', 't', 1000, '/file_pair_unchanged_added' ), | |
153 ( 'added', 't', 1000, '/file_pair_unchanged_added' ), | |
154 # File with two symbols, one unchanged, one changed, different bucket | |
155 ( 'unchanged', 't', 1000, '/file_pair_unchanged_diffbuck_changed' ), | |
156 ( 'changed', '@', 2000, '/file_pair_unchanged_diffbuck_changed' ), | |
157 # File with two symbols, one unchanged, one deleted, different bucket | |
158 ( 'unchanged', 't', 1000, '/file_pair_unchanged_diffbuck_removed' ), | |
159 # File with two symbols, one unchanged, one added, different bucket | |
160 ( 'unchanged', 't', 1000, '/file_pair_unchanged_diffbuck_added' ), | |
161 ( 'added', '@', 1000, '/file_pair_unchanged_diffbuck_added' ), | |
162 # File with four symbols, one added, one removed, one changed, one unchanged | |
163 ( 'size_changed', 't', 2000, '/file_tetra' ), | |
164 ( 'unchanged', 't', 1000, '/file_tetra' ), | |
165 ( 'added', 't', 1000, '/file_tetra' ), | |
166 # New file with one symbol added | |
167 ( 'added', 't', 1000, '/file_new' ), | |
168 ) | |
169 | |
170 # Here we go | |
171 (added, removed, changed, unchanged) = Compare(symbol_list1, symbol_list2) | |
172 | |
173 # File with one symbol, left as-is. | |
174 assert ('/file_unchanged', 't', 'unchanged', 1000, 1000) in unchanged | |
175 # File with one symbol, changed. | |
176 assert ('/file_all_changed', 't', 'changed', 1000, 2000) in changed | |
177 # File with one symbol, deleted. | |
178 assert ('/file_all_deleted', 't', 'removed', 1000, None) in removed | |
179 # New file with one symbol added | |
180 assert ('/file_new', 't', 'added', None, 1000) in added | |
181 # File with two symbols, one unchanged, one changed, same bucket | |
182 assert ('/file_pair_unchanged_changed', | |
183 't', 'unchanged', 1000, 1000) in unchanged | |
184 assert ('/file_pair_unchanged_changed', | |
185 't', 'changed', 1000, 2000) in changed | |
186 # File with two symbols, one unchanged, one removed, same bucket | |
187 assert ('/file_pair_unchanged_removed', | |
188 't', 'unchanged', 1000, 1000) in unchanged | |
189 assert ('/file_pair_unchanged_removed', | |
190 't', 'removed', 1000, None) in removed | |
191 # File with two symbols, one unchanged, one added, same bucket | |
192 assert ('/file_pair_unchanged_added', | |
193 't', 'unchanged', 1000, 1000) in unchanged | |
194 assert ('/file_pair_unchanged_added', | |
195 't', 'added', None, 1000) in added | |
196 # File with two symbols, one unchanged, one changed, different bucket | |
197 assert ('/file_pair_unchanged_diffbuck_changed', | |
198 't', 'unchanged', 1000, 1000) in unchanged | |
199 assert ('/file_pair_unchanged_diffbuck_changed', | |
200 '@', 'changed', 1000, 2000) in changed | |
201 # File with two symbols, one unchanged, one removed, different bucket | |
202 assert ('/file_pair_unchanged_diffbuck_removed', | |
203 't', 'unchanged', 1000, 1000) in unchanged | |
204 assert ('/file_pair_unchanged_diffbuck_removed', | |
205 '@', 'removed', 1000, None) in removed | |
206 # File with two symbols, one unchanged, one added, different bucket | |
207 assert ('/file_pair_unchanged_diffbuck_added', | |
208 't', 'unchanged', 1000, 1000) in unchanged | |
209 assert ('/file_pair_unchanged_diffbuck_added', | |
210 '@', 'added', None, 1000) in added | |
211 # File with four symbols, one added, one removed, one changed, one unchanged | |
212 assert ('/file_tetra', 't', 'size_changed', 1000, 2000) in changed | |
213 assert ('/file_tetra', 't', 'unchanged', 1000, 1000) in unchanged | |
214 assert ('/file_tetra', 't', 'added', None, 1000) in added | |
215 assert ('/file_tetra', 't', 'removed', 1000, None) in removed | |
216 | |
217 # Now check final stats. | |
218 CrunchStats(added, removed, changed, unchanged, True, True) | |
219 | |
220 | |
221 def CrunchStats(added, removed, changed, unchanged, showsources, showsymbols): | 110 def CrunchStats(added, removed, changed, unchanged, showsources, showsymbols): |
222 """Outputs to stdout a summary of changes based on the symbol lists.""" | 111 """Outputs to stdout a summary of changes based on the symbol lists.""" |
223 print 'Symbol statistics:' | 112 print 'Symbol statistics:' |
224 sources_with_new_symbols = set() | 113 sources_with_new_symbols = set() |
225 new_symbols_size = 0 | 114 new_symbols_size = 0 |
226 new_symbols_by_path = {} | 115 new_symbols_by_path = {} |
227 for file_path, symbol_type, symbol_name, size1, size2 in added: | 116 for file_path, symbol_type, symbol_name, size1, size2 in added: |
228 sources_with_new_symbols.add(file_path) | 117 sources_with_new_symbols.add(file_path) |
229 new_symbols_size += size2 | 118 new_symbols_size += size2 |
230 bucket = new_symbols_by_path.setdefault(file_path, []) | 119 bucket = new_symbols_by_path.setdefault(file_path, []) |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 removed_sources = (sources_with_removed_symbols - | 166 removed_sources = (sources_with_removed_symbols - |
278 maybe_unchanged_sources - | 167 maybe_unchanged_sources - |
279 sources_with_new_symbols) | 168 sources_with_new_symbols) |
280 partially_changed_sources = (sources_with_changed_symbols | | 169 partially_changed_sources = (sources_with_changed_symbols | |
281 sources_with_new_symbols | | 170 sources_with_new_symbols | |
282 sources_with_removed_symbols) - removed_sources - new_sources | 171 sources_with_removed_symbols) - removed_sources - new_sources |
283 allFiles = (sources_with_new_symbols | | 172 allFiles = (sources_with_new_symbols | |
284 sources_with_removed_symbols | | 173 sources_with_removed_symbols | |
285 sources_with_changed_symbols | | 174 sources_with_changed_symbols | |
286 maybe_unchanged_sources) | 175 maybe_unchanged_sources) |
287 print 'Source stats: ' | 176 print 'Source stats:' |
288 print(' %d sources encountered.' % len(allFiles)) | 177 print(' %d sources encountered.' % len(allFiles)) |
289 print(' %d completely new.' % len(new_sources)) | 178 print(' %d completely new.' % len(new_sources)) |
290 print(' %d removed completely.' % len(removed_sources)) | 179 print(' %d removed completely.' % len(removed_sources)) |
291 print(' %d partially changed.' % len(partially_changed_sources)) | 180 print(' %d partially changed.' % len(partially_changed_sources)) |
292 print(' %d completely unchanged.' % len(unchanged_sources)) | 181 print(' %d completely unchanged.' % len(unchanged_sources)) |
293 remainder = (allFiles - new_sources - removed_sources - | 182 remainder = (allFiles - new_sources - removed_sources - |
294 partially_changed_sources - unchanged_sources) | 183 partially_changed_sources - unchanged_sources) |
295 assert len(remainder) == 0 | 184 assert len(remainder) == 0 |
296 | 185 |
297 if not showsources: | 186 if not showsources: |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 parser.add_option('--nm1', metavar='PATH', | 261 parser.add_option('--nm1', metavar='PATH', |
373 help='the nm dump of the first library') | 262 help='the nm dump of the first library') |
374 parser.add_option('--nm2', metavar='PATH', | 263 parser.add_option('--nm2', metavar='PATH', |
375 help='the nm dump of the second library') | 264 help='the nm dump of the second library') |
376 parser.add_option('--showsources', action='store_true', default=False, | 265 parser.add_option('--showsources', action='store_true', default=False, |
377 help='show per-source statistics') | 266 help='show per-source statistics') |
378 parser.add_option('--showsymbols', action='store_true', default=False, | 267 parser.add_option('--showsymbols', action='store_true', default=False, |
379 help='show all symbol information; implies --showfiles') | 268 help='show all symbol information; implies --showfiles') |
380 parser.add_option('--verbose', action='store_true', default=False, | 269 parser.add_option('--verbose', action='store_true', default=False, |
381 help='output internal debugging stuff') | 270 help='output internal debugging stuff') |
382 parser.add_option('--selftest', action='store_true', default=False, | |
383 help='run internal diagnosis') | |
384 opts, _args = parser.parse_args() | 271 opts, _args = parser.parse_args() |
385 | 272 |
386 if opts.selftest: | |
387 TestCompare() | |
388 return | |
389 | |
390 if not opts.nm1: | 273 if not opts.nm1: |
391 parser.error('--nm1 is required') | 274 parser.error('--nm1 is required') |
392 if not opts.nm2: | 275 if not opts.nm2: |
393 parser.error('--nm2 is required') | 276 parser.error('--nm2 is required') |
394 symbols = [] | 277 symbols = [] |
395 for path in [opts.nm1, opts.nm2]: | 278 for path in [opts.nm1, opts.nm2]: |
396 with file(path, 'r') as nm_input: | 279 with file(path, 'r') as nm_input: |
397 if opts.verbose: | 280 if opts.verbose: |
398 print 'parsing ' + path + '...' | 281 print 'parsing ' + path + '...' |
399 symbols.append(list(binary_size_utils.ParseNm(nm_input))) | 282 symbols.append(list(binary_size_utils.ParseNm(nm_input))) |
400 (added, removed, changed, unchanged) = Compare(symbols[0], symbols[1]) | 283 (added, removed, changed, unchanged) = Compare(symbols[0], symbols[1]) |
401 CrunchStats(added, removed, changed, unchanged, | 284 CrunchStats(added, removed, changed, unchanged, |
402 opts.showsources | opts.showsymbols, opts.showsymbols) | 285 opts.showsources | opts.showsymbols, opts.showsymbols) |
403 | 286 |
404 if __name__ == '__main__': | 287 if __name__ == '__main__': |
405 sys.exit(main()) | 288 sys.exit(main()) |
OLD | NEW |