Index: tools/binary_size/explain_binary_size_delta.py |
diff --git a/tools/binary_size/explain_binary_size_delta.py b/tools/binary_size/explain_binary_size_delta.py |
index 88a517bf2738adddc1c0d098f530da7c62a6a449..cb99fe6cc93981b3bec3ecff66e8ea0cb1a9fa07 100755 |
--- a/tools/binary_size/explain_binary_size_delta.py |
+++ b/tools/binary_size/explain_binary_size_delta.py |
@@ -37,6 +37,7 @@ dumps. Example: |
explain_binary_size_delta.py --nm1 /tmp/nm1.dump --nm2 /tmp/nm2.dump |
""" |
+import collections |
import operator |
import optparse |
import os |
@@ -69,7 +70,8 @@ def Compare(symbols1, symbols2): |
file_path = '(No Path)' |
key = (file_path, symbol_type) |
bucket = cache.setdefault(key, {}) |
- bucket[symbol_name] = symbol_size |
+ size_list = bucket.setdefault(symbol_name, []) |
+ size_list.append(symbol_size) |
# Now diff them. We iterate over the elements in cache1. For each symbol |
# that we find in cache2, we record whether it was deleted, changed, or |
@@ -79,32 +81,61 @@ def Compare(symbols1, symbols2): |
bucket2 = cache2.get(key) |
if not bucket2: |
# A file was removed. Everything in bucket1 is dead. |
- for symbol_name, symbol_size in bucket1.items(): |
- removed.append((key[0], key[1], symbol_name, symbol_size, None)) |
+ for symbol_name, symbol_size_list in bucket1.items(): |
+ for symbol_size in symbol_size_list: |
+ removed.append((key[0], key[1], symbol_name, symbol_size, None)) |
else: |
# File still exists, look for changes within. |
- for symbol_name, symbol_size in bucket1.items(): |
- size2 = bucket2.get(symbol_name) |
- if size2 is None: |
+ for symbol_name, symbol_size_list in bucket1.items(): |
+ size_list2 = bucket2.get(symbol_name) |
+ if size_list2 is None: |
# Symbol no longer exists in bucket2. |
- removed.append((key[0], key[1], symbol_name, symbol_size, None)) |
+ for symbol_size in symbol_size_list: |
+ removed.append((key[0], key[1], symbol_name, symbol_size, None)) |
else: |
del bucket2[symbol_name] # Symbol is not new, delete from cache2. |
+ if len(symbol_size_list) == 1 and len(size_list2) == 1: |
+ symbol_size = symbol_size_list[0] |
+ size2 = size_list2[0] |
+ if symbol_size != size2: |
+ # Symbol has change size in bucket. |
+ changed.append((key[0], key[1], symbol_name, symbol_size, size2)) |
+ else: |
+ # Symbol is unchanged. |
+ unchanged.append((key[0], key[1], symbol_name, symbol_size, |
+ size2)) |
+ else: |
+ # Complex comparison for when a symbol exists multiple times |
+ # in the same file (where file can be "unknown file"). |
+ symbol_size_counter = collections.Counter(symbol_size_list) |
+ delta_counter = collections.Counter(symbol_size_list) |
+ delta_counter.subtract(size_list2) |
+ for symbol_size in sorted(delta_counter.keys()): |
+ delta = delta_counter[symbol_size] |
+ unchanged_count = symbol_size_counter[symbol_size] |
+ if delta > 0: |
+ unchanged_count -= delta |
+ for _ in range(unchanged_count): |
+ unchanged.append((key[0], key[1], symbol_name, symbol_size, |
+ symbol_size)) |
+ if delta > 0: # Used to be more of these than there is now. |
+ for _ in range(delta): |
+ removed.append((key[0], key[1], symbol_name, symbol_size, |
+ None)) |
+ elif delta < 0: # More of this (symbol,size) now. |
+ for _ in range(-delta): |
+ added.append((key[0], key[1], symbol_name, None, symbol_size)) |
+ |
if len(bucket2) == 0: |
del cache1[key] # Entire bucket is empty, delete from cache2 |
- if symbol_size != size2: |
- # Symbol has change size in bucket. |
- changed.append((key[0], key[1], symbol_name, symbol_size, size2)) |
- else: |
- # Symbol is unchanged. |
- unchanged.append((key[0], key[1], symbol_name, symbol_size, size2)) |
# We have now analyzed all symbols that are in cache1 and removed all of |
# the encountered symbols from cache2. What's left in cache2 is the new |
# symbols. |
for key, bucket2 in cache2.iteritems(): |
- for symbol_name, symbol_size in bucket2.items(): |
- added.append((key[0], key[1], symbol_name, None, symbol_size)) |
+ for symbol_name, symbol_size_list in bucket2.items(): |
+ for symbol_size in symbol_size_list: |
+ added.append((key[0], key[1], symbol_name, None, symbol_size)) |
return (added, removed, changed, unchanged) |
def DeltaStr(number): |