summaryrefslogtreecommitdiffstats
path: root/tools/binary_size
diff options
context:
space:
mode:
authorbratell@opera.com <bratell@opera.com@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-16 22:13:04 +0000
committerbratell@opera.com <bratell@opera.com@0039d316-1c4b-4281-b951-d872f2087c98>2014-07-16 22:13:04 +0000
commit474775afeecaeea12324c2ad038543b3af575eb3 (patch)
treefad5df0d080b3586aa20f9c618b3a74bfcec283c /tools/binary_size
parent205c42c4465dfb1f7d11c4b148cbf75242157da2 (diff)
downloadchromium_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-xtools/binary_size/explain_binary_size_delta.py241
-rwxr-xr-xtools/binary_size/explain_binary_size_delta_unittest.py117
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