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

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

Issue 551203004: Binary size tool, handle symbols with no path better. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 3 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 | « no previous file | tools/binary_size/explain_binary_size_delta_unittest.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 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 19 matching lines...) Expand all
30 --destdir /tmp/throwaway 30 --destdir /tmp/throwaway
31 --nm-out /tmp/nm2.dump 31 --nm-out /tmp/nm2.dump
32 32
33 # cleanup useless files 33 # cleanup useless files
34 rm -r /tmp/throwaway 34 rm -r /tmp/throwaway
35 35
36 # run this tool 36 # run this tool
37 explain_binary_size_delta.py --nm1 /tmp/nm1.dump --nm2 /tmp/nm2.dump 37 explain_binary_size_delta.py --nm1 /tmp/nm1.dump --nm2 /tmp/nm2.dump
38 """ 38 """
39 39
40 import collections
40 import operator 41 import operator
41 import optparse 42 import optparse
42 import os 43 import os
43 import sys 44 import sys
44 45
45 import binary_size_utils 46 import binary_size_utils
46 47
47 48
48 def Compare(symbols1, symbols2): 49 def Compare(symbols1, symbols2):
49 """Executes a comparison of the symbols in symbols1 and symbols2. 50 """Executes a comparison of the symbols in symbols1 and symbols2.
(...skipping 12 matching lines...) Expand all
62 for cache, symbols in ((cache1, symbols1), (cache2, symbols2)): 63 for cache, symbols in ((cache1, symbols1), (cache2, symbols2)):
63 for symbol_name, symbol_type, symbol_size, file_path in symbols: 64 for symbol_name, symbol_type, symbol_size, file_path in symbols:
64 if 'vtable for ' in symbol_name: 65 if 'vtable for ' in symbol_name:
65 symbol_type = '@' # hack to categorize these separately 66 symbol_type = '@' # hack to categorize these separately
66 if file_path: 67 if file_path:
67 file_path = os.path.normpath(file_path) 68 file_path = os.path.normpath(file_path)
68 else: 69 else:
69 file_path = '(No Path)' 70 file_path = '(No Path)'
70 key = (file_path, symbol_type) 71 key = (file_path, symbol_type)
71 bucket = cache.setdefault(key, {}) 72 bucket = cache.setdefault(key, {})
72 bucket[symbol_name] = symbol_size 73 size_list = bucket.setdefault(symbol_name, [])
74 size_list.append(symbol_size)
73 75
74 # Now diff them. We iterate over the elements in cache1. For each symbol 76 # Now diff them. We iterate over the elements in cache1. For each symbol
75 # that we find in cache2, we record whether it was deleted, changed, or 77 # that we find in cache2, we record whether it was deleted, changed, or
76 # unchanged. We then remove it from cache2; all the symbols that remain 78 # unchanged. We then remove it from cache2; all the symbols that remain
77 # in cache2 at the end of the iteration over cache1 are the 'new' symbols. 79 # in cache2 at the end of the iteration over cache1 are the 'new' symbols.
78 for key, bucket1 in cache1.items(): 80 for key, bucket1 in cache1.items():
79 bucket2 = cache2.get(key) 81 bucket2 = cache2.get(key)
80 if not bucket2: 82 if not bucket2:
81 # A file was removed. Everything in bucket1 is dead. 83 # A file was removed. Everything in bucket1 is dead.
82 for symbol_name, symbol_size in bucket1.items(): 84 for symbol_name, symbol_size_list in bucket1.items():
83 removed.append((key[0], key[1], symbol_name, symbol_size, None)) 85 for symbol_size in symbol_size_list:
86 removed.append((key[0], key[1], symbol_name, symbol_size, None))
84 else: 87 else:
85 # File still exists, look for changes within. 88 # File still exists, look for changes within.
86 for symbol_name, symbol_size in bucket1.items(): 89 for symbol_name, symbol_size_list in bucket1.items():
87 size2 = bucket2.get(symbol_name) 90 size_list2 = bucket2.get(symbol_name)
88 if size2 is None: 91 if size_list2 is None:
89 # Symbol no longer exists in bucket2. 92 # Symbol no longer exists in bucket2.
90 removed.append((key[0], key[1], symbol_name, symbol_size, None)) 93 for symbol_size in symbol_size_list:
94 removed.append((key[0], key[1], symbol_name, symbol_size, None))
91 else: 95 else:
92 del bucket2[symbol_name] # Symbol is not new, delete from cache2. 96 del bucket2[symbol_name] # Symbol is not new, delete from cache2.
97 if len(symbol_size_list) == 1 and len(size_list2) == 1:
98 symbol_size = symbol_size_list[0]
99 size2 = size_list2[0]
100 if symbol_size != size2:
101 # Symbol has change size in bucket.
102 changed.append((key[0], key[1], symbol_name, symbol_size, size2))
103 else:
104 # Symbol is unchanged.
105 unchanged.append((key[0], key[1], symbol_name, symbol_size,
106 size2))
107 else:
108 # Complex comparison for when a symbol exists multiple times
109 # in the same file (where file can be "unknown file").
110 symbol_size_counter = collections.Counter(symbol_size_list)
111 delta_counter = collections.Counter(symbol_size_list)
112 delta_counter.subtract(size_list2)
113 for symbol_size in sorted(delta_counter.keys()):
114 delta = delta_counter[symbol_size]
115 unchanged_count = symbol_size_counter[symbol_size]
116 if delta > 0:
117 unchanged_count -= delta
118 for _ in range(unchanged_count):
119 unchanged.append((key[0], key[1], symbol_name, symbol_size,
120 symbol_size))
121 if delta > 0: # Used to be more of these than there is now.
122 for _ in range(delta):
123 removed.append((key[0], key[1], symbol_name, symbol_size,
124 None))
125 elif delta < 0: # More of this (symbol,size) now.
126 for _ in range(-delta):
127 added.append((key[0], key[1], symbol_name, None, symbol_size))
128
93 if len(bucket2) == 0: 129 if len(bucket2) == 0:
94 del cache1[key] # Entire bucket is empty, delete from cache2 130 del cache1[key] # Entire bucket is empty, delete from cache2
95 if symbol_size != size2:
96 # Symbol has change size in bucket.
97 changed.append((key[0], key[1], symbol_name, symbol_size, size2))
98 else:
99 # Symbol is unchanged.
100 unchanged.append((key[0], key[1], symbol_name, symbol_size, size2))
101 131
102 # We have now analyzed all symbols that are in cache1 and removed all of 132 # We have now analyzed all symbols that are in cache1 and removed all of
103 # the encountered symbols from cache2. What's left in cache2 is the new 133 # the encountered symbols from cache2. What's left in cache2 is the new
104 # symbols. 134 # symbols.
105 for key, bucket2 in cache2.iteritems(): 135 for key, bucket2 in cache2.iteritems():
106 for symbol_name, symbol_size in bucket2.items(): 136 for symbol_name, symbol_size_list in bucket2.items():
107 added.append((key[0], key[1], symbol_name, None, symbol_size)) 137 for symbol_size in symbol_size_list:
138 added.append((key[0], key[1], symbol_name, None, symbol_size))
108 return (added, removed, changed, unchanged) 139 return (added, removed, changed, unchanged)
109 140
110 def DeltaStr(number): 141 def DeltaStr(number):
111 """Returns the number as a string with a '+' prefix if it's > 0 and 142 """Returns the number as a string with a '+' prefix if it's > 0 and
112 a '-' prefix if it's < 0.""" 143 a '-' prefix if it's < 0."""
113 result = str(number) 144 result = str(number)
114 if number > 0: 145 if number > 0:
115 result = '+' + result 146 result = '+' + result
116 return result 147 return result
117 148
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 with file(path, 'r') as nm_input: 351 with file(path, 'r') as nm_input:
321 if opts.verbose: 352 if opts.verbose:
322 print 'parsing ' + path + '...' 353 print 'parsing ' + path + '...'
323 symbols.append(list(binary_size_utils.ParseNm(nm_input))) 354 symbols.append(list(binary_size_utils.ParseNm(nm_input)))
324 (added, removed, changed, unchanged) = Compare(symbols[0], symbols[1]) 355 (added, removed, changed, unchanged) = Compare(symbols[0], symbols[1])
325 CrunchStats(added, removed, changed, unchanged, 356 CrunchStats(added, removed, changed, unchanged,
326 opts.showsources | opts.showsymbols, opts.showsymbols) 357 opts.showsources | opts.showsymbols, opts.showsymbols)
327 358
328 if __name__ == '__main__': 359 if __name__ == '__main__':
329 sys.exit(main()) 360 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | tools/binary_size/explain_binary_size_delta_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698