diff options
author | bratell@opera.com <bratell@opera.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-16 22:13:04 +0000 |
---|---|---|
committer | bratell@opera.com <bratell@opera.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-16 22:13:04 +0000 |
commit | 474775afeecaeea12324c2ad038543b3af575eb3 (patch) | |
tree | fad5df0d080b3586aa20f9c618b3a74bfcec283c /tools/binary_size | |
parent | 205c42c4465dfb1f7d11c4b148cbf75242157da2 (diff) | |
download | chromium_src-474775afeecaeea12324c2ad038543b3af575eb3.zip chromium_src-474775afeecaeea12324c2ad038543b3af575eb3.tar.gz chromium_src-474775afeecaeea12324c2ad038543b3af575eb3.tar.bz2 |
Polishing binary_size tool output.
Doing some sorting and splitting of data to make large amounts
of changes easier to study.
BUG=
Review URL: https://codereview.chromium.org/375063002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@283540 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/binary_size')
-rwxr-xr-x | tools/binary_size/explain_binary_size_delta.py | 241 | ||||
-rwxr-xr-x | tools/binary_size/explain_binary_size_delta_unittest.py | 117 |
2 files changed, 210 insertions, 148 deletions
diff --git a/tools/binary_size/explain_binary_size_delta.py b/tools/binary_size/explain_binary_size_delta.py index 80683ff..88a517b 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 operator import optparse import os import sys @@ -106,46 +107,76 @@ def Compare(symbols1, symbols2): added.append((key[0], key[1], symbol_name, None, symbol_size)) return (added, removed, changed, unchanged) +def DeltaStr(number): + """Returns the number as a string with a '+' prefix if it's > 0 and + a '-' prefix if it's < 0.""" + result = str(number) + if number > 0: + result = '+' + result + return result + + +class CrunchStatsData(object): + """Stores a summary of data of a certain kind.""" + def __init__(self, symbols): + self.symbols = symbols + self.sources = set() + self.before_size = 0 + self.after_size = 0 + self.symbols_by_path = {} + def CrunchStats(added, removed, changed, unchanged, showsources, showsymbols): """Outputs to stdout a summary of changes based on the symbol lists.""" - print 'Symbol statistics:' - sources_with_new_symbols = set() - new_symbols_size = 0 - new_symbols_by_path = {} - for file_path, symbol_type, symbol_name, size1, size2 in added: - sources_with_new_symbols.add(file_path) - new_symbols_size += size2 - bucket = new_symbols_by_path.setdefault(file_path, []) - bucket.append((symbol_name, symbol_type, None, size2)) - print(' %d added, totalling %d bytes across %d sources' % - (len(added), new_symbols_size, len(sources_with_new_symbols))) - - sources_with_removed_symbols = set() - removed_symbols_size = 0 - removed_symbols_by_path = {} - for file_path, symbol_type, symbol_name, size1, size2 in removed: - sources_with_removed_symbols.add(file_path) - removed_symbols_size += size1 - bucket = removed_symbols_by_path.setdefault(file_path, []) - bucket.append((symbol_name, symbol_type, size1, None)) - print(' %d removed, totalling %d bytes removed across %d sources' % - (len(removed), removed_symbols_size, len(sources_with_removed_symbols))) - - sources_with_changed_symbols = set() - before_size = 0 - after_size = 0 - changed_symbols_by_path = {} - for file_path, symbol_type, symbol_name, size1, size2 in changed: - sources_with_changed_symbols.add(file_path) - before_size += size1 - after_size += size2 - bucket = changed_symbols_by_path.setdefault(file_path, []) - bucket.append((symbol_name, symbol_type, size1, size2)) - print(' %d changed, resulting in a net change of %d bytes ' - '(%d bytes before, %d bytes after) across %d sources' % - (len(changed), (after_size - before_size), before_size, after_size, - len(sources_with_changed_symbols))) + # Split changed into grown and shrunk because that is easier to + # discuss. + grown = [] + shrunk = [] + for item in changed: + file_path, symbol_type, symbol_name, size1, size2 = item + if size1 < size2: + grown.append(item) + else: + shrunk.append(item) + + new_symbols = CrunchStatsData(added) + removed_symbols = CrunchStatsData(removed) + grown_symbols = CrunchStatsData(grown) + shrunk_symbols = CrunchStatsData(shrunk) + sections = [new_symbols, removed_symbols, grown_symbols, shrunk_symbols] + for section in sections: + for file_path, symbol_type, symbol_name, size1, size2 in section.symbols: + section.sources.add(file_path) + if size1 is not None: + section.before_size += size1 + if size2 is not None: + section.after_size += size2 + bucket = section.symbols_by_path.setdefault(file_path, []) + bucket.append((symbol_name, symbol_type, size1, size2)) + + total_change = sum(s.after_size - s.before_size for s in sections) + summary = 'Total change: %s bytes' % DeltaStr(total_change) + print(summary) + print('=' * len(summary)) + for section in sections: + if not section.symbols: + continue + if section.before_size == 0: + description = ('added, totalling %s bytes' % DeltaStr(section.after_size)) + elif section.after_size == 0: + description = ('removed, totalling %s bytes' % + DeltaStr(-section.before_size)) + else: + if section.after_size > section.before_size: + type_str = 'grown' + else: + type_str = 'shrunk' + description = ('%s, for a net change of %s bytes ' + '(%d bytes before, %d bytes after)' % + (type_str, DeltaStr(section.after_size - section.before_size), + section.before_size, section.after_size)) + print(' %d %s across %d sources' % + (len(section.symbols), description, len(section.sources))) maybe_unchanged_sources = set() unchanged_symbols_size = 0 @@ -156,23 +187,22 @@ def CrunchStats(added, removed, changed, unchanged, showsources, showsymbols): (len(unchanged), unchanged_symbols_size)) # High level analysis, always output. - unchanged_sources = (maybe_unchanged_sources - - sources_with_changed_symbols - - sources_with_removed_symbols - - sources_with_new_symbols) - new_sources = (sources_with_new_symbols - + unchanged_sources = maybe_unchanged_sources + for section in sections: + unchanged_sources = unchanged_sources - section.sources + new_sources = (new_symbols.sources - maybe_unchanged_sources - - sources_with_removed_symbols) - removed_sources = (sources_with_removed_symbols - + removed_symbols.sources) + removed_sources = (removed_symbols.sources - maybe_unchanged_sources - - sources_with_new_symbols) - partially_changed_sources = (sources_with_changed_symbols | - sources_with_new_symbols | - sources_with_removed_symbols) - removed_sources - new_sources - allFiles = (sources_with_new_symbols | - sources_with_removed_symbols | - sources_with_changed_symbols | - maybe_unchanged_sources) + new_symbols.sources) + partially_changed_sources = (grown_symbols.sources | + shrunk_symbols.sources | new_symbols.sources | + removed_symbols.sources) - removed_sources - new_sources + allFiles = set() + for section in sections: + allFiles = allFiles | section.sources + allFiles = allFiles | maybe_unchanged_sources print 'Source stats:' print(' %d sources encountered.' % len(allFiles)) print(' %d completely new.' % len(new_sources)) @@ -187,61 +217,72 @@ def CrunchStats(added, removed, changed, unchanged, showsources, showsymbols): return # Per-source analysis, only if requested print 'Per-source Analysis:' delta_by_path = {} - for path in new_symbols_by_path: - entry = delta_by_path.get(path) - if not entry: - entry = {'plus': 0, 'minus': 0} - delta_by_path[path] = entry - for symbol_name, symbol_type, size1, size2 in new_symbols_by_path[path]: - entry['plus'] += size2 - for path in removed_symbols_by_path: - entry = delta_by_path.get(path) - if not entry: - entry = {'plus': 0, 'minus': 0} - delta_by_path[path] = entry - for symbol_name, symbol_type, size1, size2 in removed_symbols_by_path[path]: - entry['minus'] += size1 - for path in changed_symbols_by_path: - entry = delta_by_path.get(path) - if not entry: - entry = {'plus': 0, 'minus': 0} - delta_by_path[path] = entry - for symbol_name, symbol_type, size1, size2 in changed_symbols_by_path[path]: - delta = size2 - size1 - if delta > 0: - entry['plus'] += delta - else: - entry['minus'] += (-1 * delta) + for section in sections: + for path in section.symbols_by_path: + entry = delta_by_path.get(path) + if not entry: + entry = {'plus': 0, 'minus': 0} + delta_by_path[path] = entry + for symbol_name, symbol_type, size1, size2 in \ + section.symbols_by_path[path]: + if size1 is None: + delta = size2 + elif size2 is None: + delta = -size1 + else: + delta = size2 - size1 - for path in sorted(delta_by_path): - print ' Source: ' + path - size_data = delta_by_path[path] + if delta > 0: + entry['plus'] += delta + else: + entry['minus'] += (-1 * delta) + + def delta_sort_key(item): + _path, size_data = item + growth = size_data['plus'] - size_data['minus'] + return growth + + for path, size_data in sorted(delta_by_path.iteritems(), key=delta_sort_key, + reverse=True): gain = size_data['plus'] loss = size_data['minus'] delta = size_data['plus'] - size_data['minus'] - print (' Change: %d bytes (gained %d, lost %d)' % (delta, gain, loss)) + header = ' %s - Source: %s - (gained %d, lost %d)' % (DeltaStr(delta), + path, gain, loss) + divider = '-' * len(header) + print '' + print divider + print header + print divider if showsymbols: - if path in new_symbols_by_path: - print ' New symbols:' - for symbol_name, symbol_type, size1, size2 in \ - new_symbols_by_path[path]: - print (' %s type=%s, size=%d bytes' % - (symbol_name, symbol_type, size2)) - if path in removed_symbols_by_path: - print ' Removed symbols:' + if path in new_symbols.symbols_by_path: + print ' New symbols:' for symbol_name, symbol_type, size1, size2 in \ - removed_symbols_by_path[path]: - print (' %s type=%s, size=%d bytes' % - (symbol_name, symbol_type, size1)) - if path in changed_symbols_by_path: - print ' Changed symbols:' - def sortkey(item): - symbol_name, _symbol_type, size1, size2 = item - return (size1 - size2, symbol_name) + sorted(new_symbols.symbols_by_path[path], + key=operator.itemgetter(3), + reverse=True): + print (' %8s: %s type=%s, size=%d bytes' % + (DeltaStr(size2), symbol_name, symbol_type, size2)) + if path in removed_symbols.symbols_by_path: + print ' Removed symbols:' for symbol_name, symbol_type, size1, size2 in \ - sorted(changed_symbols_by_path[path], key=sortkey): - print (' %s type=%s, delta=%d bytes (was %d bytes, now %d bytes)' - % (symbol_name, symbol_type, (size2 - size1), size1, size2)) + sorted(removed_symbols.symbols_by_path[path], + key=operator.itemgetter(2)): + print (' %8s: %s type=%s, size=%d bytes' % + (DeltaStr(-size1), symbol_name, symbol_type, size1)) + for (changed_symbols_by_path, type_str) in [ + (grown_symbols.symbols_by_path, "Grown"), + (shrunk_symbols.symbols_by_path, "Shrunk")]: + if path in changed_symbols_by_path: + print ' %s symbols:' % type_str + def changed_symbol_sortkey(item): + symbol_name, _symbol_type, size1, size2 = item + return (size1 - size2, symbol_name) + for symbol_name, symbol_type, size1, size2 in \ + sorted(changed_symbols_by_path[path], key=changed_symbol_sortkey): + print (' %8s: %s type=%s, (was %d bytes, now %d bytes)' + % (DeltaStr(size2 - size1), symbol_name, + symbol_type, size1, size2)) def main(): diff --git a/tools/binary_size/explain_binary_size_delta_unittest.py b/tools/binary_size/explain_binary_size_delta_unittest.py index 6a004e2..a5f696f 100755 --- a/tools/binary_size/explain_binary_size_delta_unittest.py +++ b/tools/binary_size/explain_binary_size_delta_unittest.py @@ -136,10 +136,11 @@ class ExplainBinarySizeDeltaTest(unittest.TestCase): result = output_collector.getvalue() expected_output = """\ -Symbol statistics: - 4 added, totalling 4000 bytes across 4 sources - 4 removed, totalling 4000 bytes removed across 4 sources - 4 changed, resulting in a net change of 4000 bytes \ +Total change: +4000 bytes +========================= + 4 added, totalling +4000 bytes across 4 sources + 4 removed, totalling -4000 bytes across 4 sources + 4 grown, for a net change of +4000 bytes \ (4000 bytes before, 8000 bytes after) across 4 sources 8 unchanged, totalling 8000 bytes Source stats: @@ -149,50 +150,70 @@ Source stats: 8 partially changed. 1 completely unchanged. Per-source Analysis: - Source: /file_all_changed - Change: 1000 bytes (gained 1000, lost 0) - Changed symbols: - changed type=t, delta=1000 bytes (was 1000 bytes, now 2000 bytes) - Source: /file_all_deleted - Change: -1000 bytes (gained 0, lost 1000) - Removed symbols: - removed type=t, size=1000 bytes - Source: /file_new - Change: 1000 bytes (gained 1000, lost 0) - New symbols: - added type=t, size=1000 bytes - Source: /file_pair_unchanged_added - Change: 1000 bytes (gained 1000, lost 0) - New symbols: - added type=t, size=1000 bytes - Source: /file_pair_unchanged_changed - Change: 1000 bytes (gained 1000, lost 0) - Changed symbols: - changed type=t, delta=1000 bytes (was 1000 bytes, now 2000 bytes) - Source: /file_pair_unchanged_diffbuck_added - Change: 1000 bytes (gained 1000, lost 0) - New symbols: - added type=@, size=1000 bytes - Source: /file_pair_unchanged_diffbuck_changed - Change: 1000 bytes (gained 1000, lost 0) - Changed symbols: - changed type=@, delta=1000 bytes (was 1000 bytes, now 2000 bytes) - Source: /file_pair_unchanged_diffbuck_removed - Change: -1000 bytes (gained 0, lost 1000) - Removed symbols: - removed type=@, size=1000 bytes - Source: /file_pair_unchanged_removed - Change: -1000 bytes (gained 0, lost 1000) - Removed symbols: - removed type=t, size=1000 bytes - Source: /file_tetra - Change: 1000 bytes (gained 2000, lost 1000) - New symbols: - added type=t, size=1000 bytes - Removed symbols: - removed type=t, size=1000 bytes - Changed symbols: - size_changed type=t, delta=1000 bytes (was 1000 bytes, now 2000 bytes) + +-------------------------------------------------- + +1000 - Source: /file_new - (gained 1000, lost 0) +-------------------------------------------------- + New symbols: + +1000: added type=t, size=1000 bytes + +--------------------------------------------------------------------- + +1000 - Source: /file_pair_unchanged_changed - (gained 1000, lost 0) +--------------------------------------------------------------------- + Grown symbols: + +1000: changed type=t, (was 1000 bytes, now 2000 bytes) + +---------------------------------------------------------------------------- + +1000 - Source: /file_pair_unchanged_diffbuck_added - (gained 1000, lost 0) +---------------------------------------------------------------------------- + New symbols: + +1000: added type=@, size=1000 bytes + +------------------------------------------------------------------- + +1000 - Source: /file_pair_unchanged_added - (gained 1000, lost 0) +------------------------------------------------------------------- + New symbols: + +1000: added type=t, size=1000 bytes + +------------------------------------------------------------------------------ + +1000 - Source: /file_pair_unchanged_diffbuck_changed - (gained 1000, lost 0) +------------------------------------------------------------------------------ + Grown symbols: + +1000: changed type=@, (was 1000 bytes, now 2000 bytes) + +---------------------------------------------------------- + +1000 - Source: /file_all_changed - (gained 1000, lost 0) +---------------------------------------------------------- + Grown symbols: + +1000: changed type=t, (was 1000 bytes, now 2000 bytes) + +------------------------------------------------------- + +1000 - Source: /file_tetra - (gained 2000, lost 1000) +------------------------------------------------------- + New symbols: + +1000: added type=t, size=1000 bytes + Removed symbols: + -1000: removed type=t, size=1000 bytes + Grown symbols: + +1000: size_changed type=t, (was 1000 bytes, now 2000 bytes) + +------------------------------------------------------------------------------ + -1000 - Source: /file_pair_unchanged_diffbuck_removed - (gained 0, lost 1000) +------------------------------------------------------------------------------ + Removed symbols: + -1000: removed type=@, size=1000 bytes + +---------------------------------------------------------- + -1000 - Source: /file_all_deleted - (gained 0, lost 1000) +---------------------------------------------------------- + Removed symbols: + -1000: removed type=t, size=1000 bytes + +--------------------------------------------------------------------- + -1000 - Source: /file_pair_unchanged_removed - (gained 0, lost 1000) +--------------------------------------------------------------------- + Removed symbols: + -1000: removed type=t, size=1000 bytes """ self.maxDiff = None |