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

Unified Diff: tools/binary_size/describe.py

Issue 2785483002: Reland of V2 of //tools/binary_size rewrite (diffs). (Closed)
Patch Set: add missing name= Created 3 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/binary_size/create_html_breakdown.py ('k') | tools/binary_size/explain_binary_size_delta.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/binary_size/describe.py
diff --git a/tools/binary_size/describe.py b/tools/binary_size/describe.py
new file mode 100644
index 0000000000000000000000000000000000000000..f64992da1e1b877aa40e836daa7d5a36ce68478c
--- /dev/null
+++ b/tools/binary_size/describe.py
@@ -0,0 +1,139 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Methods for converting model objects to human-readable formats."""
+
+import itertools
+
+import models
+
+
+class Describer(object):
+ def __init__(self, verbose=False):
+ self.verbose = verbose
+
+ def _DescribeSectionSizes(self, section_sizes):
+ relevant_names = models.SECTION_TO_SECTION_NAME.values()
+ section_names = sorted(k for k in section_sizes.iterkeys()
+ if k in relevant_names or k.startswith('.data'))
+ total_bytes = sum(v for k, v in section_sizes.iteritems()
+ if k in section_names and k != '.bss')
+ yield 'Section Sizes (Total={:,} bytes):'.format(total_bytes)
+ for name in section_names:
+ size = section_sizes[name]
+ if name == '.bss':
+ yield '{}: {:,} bytes (not included in totals)'.format(name, size)
+ else:
+ percent = float(size) / total_bytes if total_bytes else 0
+ yield '{}: {:,} bytes ({:.1%})'.format(name, size, percent)
+
+ def _DescribeSymbol(self, sym):
+ # SymbolGroups are passed here when we don't want to expand them.
+ if sym.IsGroup():
+ yield '{} {:<8} {} (count={})'.format(sym.section, sym.size, sym.name,
+ len(sym))
+ return
+
+ yield '{}@0x{:<8x} {:<7} {}'.format(
+ sym.section, sym.address, sym.size, sym.path or '<no path>')
+ if sym.name:
+ yield '{:22}{}'.format('', sym.name)
+
+ def _DescribeSymbolGroup(self, group, prefix_func=None):
+ yield 'Showing {:,} symbols with total size: {:} bytes'.format(
+ len(group), group.size)
+ yield 'First columns are: running total, type, size'
+
+ running_total = 0
+ prefix = ''
+
+ for s in group.Sorted():
+ if group.IsBss() or not s.IsBss():
+ running_total += s.size
+ if prefix_func:
+ prefix = prefix_func(s)
+ for l in self._DescribeSymbol(s):
+ yield '{}{:8} {}'.format(prefix, running_total, l)
+
+ def _DescribeSymbolDiff(self, diff):
+ template = ('{} symbols added (+), {} changed (~), {} removed (-), '
+ '{} unchanged ({})')
+ unchanged_msg = '=' if self.verbose else 'not shown'
+ header_str = (template.format(
+ diff.added_count, diff.changed_count, diff.removed_count,
+ diff.unchanged_count, unchanged_msg))
+
+ def prefix_func(sym):
+ if diff.IsAdded(sym):
+ return '+ '
+ if diff.IsRemoved(sym):
+ return '- '
+ if sym.size:
+ return '~ '
+ return '= '
+
+ diff = diff if self.verbose else diff.WhereNotUnchanged()
+ group_desc = self._DescribeSymbolGroup(diff, prefix_func=prefix_func)
+ return itertools.chain((header_str,), group_desc)
+
+ def GenerateLines(self, obj):
+ if isinstance(obj, models.SizeInfo):
+ section_desc = self._DescribeSectionSizes(obj.section_sizes)
+ group_desc = self.GenerateLines(obj.symbols)
+ return itertools.chain(section_desc, ('',), group_desc)
+
+ if isinstance(obj, models.SymbolDiff):
+ return self._DescribeSymbolDiff(obj)
+
+ if isinstance(obj, models.SymbolGroup):
+ return self._DescribeSymbolGroup(obj)
+
+ if isinstance(obj, models.Symbol):
+ return self._DescribeSymbol(obj)
+
+ return (repr(obj),)
+
+
+def DescribeSizeInfoCoverage(size_info):
+ """Yields lines describing how accurate |size_info| is."""
+ for section in models.SECTION_TO_SECTION_NAME:
+ if section == 'd':
+ expected_size = sum(v for k, v in size_info.section_sizes.iteritems()
+ if k.startswith('.data'))
+ else:
+ expected_size = size_info.section_sizes[
+ models.SECTION_TO_SECTION_NAME[section]]
+
+ def one_stat(group):
+ template = ('Section %s has %.1f%% of %d bytes accounted for from '
+ '%d symbols. %d bytes are unaccounted for. Padding '
+ 'accounts for %d bytes')
+ actual_size = group.size
+ count = len(group)
+ padding = group.padding
+ size_percent = 100.0 * actual_size / expected_size
+ return (template % (section, size_percent, actual_size, count,
+ expected_size - actual_size, padding))
+
+ in_section = size_info.symbols.WhereInSection(section)
+ yield one_stat(in_section)
+
+ star_syms = in_section.WhereNameMatches(r'^\*')
+ attributed_syms = star_syms.Inverted().WhereHasAnyAttribution()
+ anonymous_syms = attributed_syms.Inverted()
+ if star_syms or anonymous_syms:
+ missing_size = star_syms.size + anonymous_syms.size
+ yield ('+ Without %d merge sections and %d anonymous entries ('
+ 'accounting for %d bytes):') % (
+ len(star_syms), len(anonymous_syms), missing_size)
+ yield '+ ' + one_stat(attributed_syms)
+
+
+def GenerateLines(obj, verbose=False):
+ return Describer(verbose).GenerateLines(obj)
+
+
+def WriteLines(lines, func):
+ for l in lines:
+ func(l)
+ func('\n')
« no previous file with comments | « tools/binary_size/create_html_breakdown.py ('k') | tools/binary_size/explain_binary_size_delta.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698