| Index: tools/binary_size/run_binary_size_analysis.py
|
| diff --git a/tools/binary_size/run_binary_size_analysis.py b/tools/binary_size/run_binary_size_analysis.py
|
| index c218effa764a7139285801df6be9dd8b4e2e7d9a..68982528f8366203527bba54ef9bd680df644f9f 100755
|
| --- a/tools/binary_size/run_binary_size_analysis.py
|
| +++ b/tools/binary_size/run_binary_size_analysis.py
|
| @@ -26,7 +26,7 @@ import time
|
|
|
| import binary_size_utils
|
|
|
| -# This path changee is not beautiful. Temporary (I hope) measure until
|
| +# This path change is not beautiful. Temporary (I hope) measure until
|
| # the chromium project has figured out a proper way to organize the
|
| # library of python tools. http://crbug.com/375725
|
| elf_symbolizer_path = os.path.abspath(os.path.join(
|
| @@ -220,140 +220,6 @@ def MakeCompactTree(symbols, symbol_path_origin_dir):
|
| return result
|
|
|
|
|
| -# TODO(andrewhayden): Only used for legacy reports. Delete.
|
| -def TreeifySymbols(symbols):
|
| - """Convert symbols into a path-based tree, calculating size information
|
| - along the way.
|
| -
|
| - The result is a dictionary that contains two kinds of nodes:
|
| - 1. Leaf nodes, representing source code locations (e.g., c++ files)
|
| - These nodes have the following dictionary entries:
|
| - sizes: a dictionary whose keys are categories (such as code, data,
|
| - vtable, etceteras) and whose values are the size, in bytes, of
|
| - those categories;
|
| - size: the total size, in bytes, of all the entries in the sizes dict
|
| - 2. Non-leaf nodes, representing directories
|
| - These nodes have the following dictionary entries:
|
| - children: a dictionary whose keys are names (path entries; either
|
| - directory or file names) and whose values are other nodes;
|
| - size: the total size, in bytes, of all the leaf nodes that are
|
| - contained within the children dict (recursively expanded)
|
| -
|
| - The result object is itself a dictionary that represents the common ancestor
|
| - of all child nodes, e.g. a path to which all other nodes beneath it are
|
| - relative. The 'size' attribute of this dict yields the sum of the size of all
|
| - leaf nodes within the data structure.
|
| - """
|
| - dirs = {'children': {}, 'size': 0}
|
| - for sym, symbol_type, size, path in symbols:
|
| - dirs['size'] += size
|
| - if path:
|
| - path = os.path.normpath(path)
|
| - if path.startswith('/'):
|
| - path = path[1:]
|
| -
|
| - parts = None
|
| - if path:
|
| - parts = path.split('/')
|
| -
|
| - if parts:
|
| - assert path
|
| - file_key = parts.pop()
|
| - tree = dirs
|
| - try:
|
| - # Traverse the tree to the parent of the file node, creating as needed
|
| - for part in parts:
|
| - assert part != ''
|
| - if part not in tree['children']:
|
| - tree['children'][part] = {'children': {}, 'size': 0}
|
| - tree = tree['children'][part]
|
| - tree['size'] += size
|
| -
|
| - # Get (creating if necessary) the node for the file
|
| - # This node doesn't have a 'children' attribute
|
| - if file_key not in tree['children']:
|
| - tree['children'][file_key] = {'sizes': collections.defaultdict(int),
|
| - 'size': 0}
|
| - tree = tree['children'][file_key]
|
| - tree['size'] += size
|
| -
|
| - # Accumulate size into a bucket within the file
|
| - symbol_type = symbol_type.lower()
|
| - if 'vtable for ' in sym:
|
| - tree['sizes']['[vtable]'] += size
|
| - elif 'r' == symbol_type:
|
| - tree['sizes']['[rodata]'] += size
|
| - elif 'd' == symbol_type:
|
| - tree['sizes']['[data]'] += size
|
| - elif 'b' == symbol_type:
|
| - tree['sizes']['[bss]'] += size
|
| - elif 't' == symbol_type:
|
| - # 'text' in binary parlance means 'code'.
|
| - tree['sizes']['[code]'] += size
|
| - elif 'w' == symbol_type:
|
| - tree['sizes']['[weak]'] += size
|
| - else:
|
| - tree['sizes']['[other]'] += size
|
| - except:
|
| - print >> sys.stderr, sym, parts, file_key
|
| - raise
|
| - else:
|
| - key = 'symbols without paths'
|
| - if key not in dirs['children']:
|
| - dirs['children'][key] = {'sizes': collections.defaultdict(int),
|
| - 'size': 0}
|
| - tree = dirs['children'][key]
|
| - subkey = 'misc'
|
| - if (sym.endswith('::__FUNCTION__') or
|
| - sym.endswith('::__PRETTY_FUNCTION__')):
|
| - subkey = '__FUNCTION__'
|
| - elif sym.startswith('CSWTCH.'):
|
| - subkey = 'CSWTCH'
|
| - elif '::' in sym:
|
| - subkey = sym[0:sym.find('::') + 2]
|
| - tree['sizes'][subkey] = tree['sizes'].get(subkey, 0) + size
|
| - tree['size'] += size
|
| - return dirs
|
| -
|
| -
|
| -# TODO(andrewhayden): Only used for legacy reports. Delete.
|
| -def JsonifyTree(tree, name):
|
| - """Convert TreeifySymbols output to a JSON treemap.
|
| -
|
| - The format is very similar, with the notable exceptions being
|
| - lists of children instead of maps and some different attribute names."""
|
| - children = []
|
| - css_class_map = {
|
| - '[vtable]': 'vtable',
|
| - '[rodata]': 'read-only_data',
|
| - '[data]': 'data',
|
| - '[bss]': 'bss',
|
| - '[code]': 'code',
|
| - '[weak]': 'weak_symbol'
|
| - }
|
| - if 'children' in tree:
|
| - # Non-leaf node. Recurse.
|
| - for child_name, child in tree['children'].iteritems():
|
| - children.append(JsonifyTree(child, child_name))
|
| - else:
|
| - # Leaf node; dump per-file stats as entries in the treemap
|
| - for kind, size in tree['sizes'].iteritems():
|
| - child_json = {'name': kind + ' (' + FormatBytes(size) + ')',
|
| - 'data': { '$area': size }}
|
| - css_class = css_class_map.get(kind)
|
| - if css_class is not None:
|
| - child_json['data']['$symbol'] = css_class
|
| - children.append(child_json)
|
| - # Sort children by size, largest to smallest.
|
| - children.sort(key=lambda child: -child['data']['$area'])
|
| -
|
| - # For leaf nodes, the 'size' attribute is the size of the leaf;
|
| - # Non-leaf nodes don't really have a size, but their 'size' attribute is
|
| - # the sum of the sizes of all their children.
|
| - return {'name': name + ' (' + FormatBytes(tree['size']) + ')',
|
| - 'data': { '$area': tree['size'] },
|
| - 'children': children }
|
| -
|
| def DumpCompactTree(symbols, symbol_path_origin_dir, outfile):
|
| tree_root = MakeCompactTree(symbols, symbol_path_origin_dir)
|
| with open(outfile, 'w') as out:
|
| @@ -363,45 +229,6 @@ def DumpCompactTree(symbols, symbol_path_origin_dir, outfile):
|
| print('Writing %d bytes json' % os.path.getsize(outfile))
|
|
|
|
|
| -# TODO(andrewhayden): Only used for legacy reports. Delete.
|
| -def DumpTreemap(symbols, outfile):
|
| - dirs = TreeifySymbols(symbols)
|
| - out = open(outfile, 'w')
|
| - try:
|
| - out.write('var kTree = ' + json.dumps(JsonifyTree(dirs, '/')))
|
| - finally:
|
| - out.flush()
|
| - out.close()
|
| -
|
| -
|
| -# TODO(andrewhayden): Only used for legacy reports. Delete.
|
| -def DumpLargestSymbols(symbols, outfile, n):
|
| - # a list of (sym, symbol_type, size, path); sort by size.
|
| - symbols = sorted(symbols, key=lambda x: -x[2])
|
| - dumped = 0
|
| - out = open(outfile, 'w')
|
| - try:
|
| - out.write('var largestSymbols = [\n')
|
| - for sym, symbol_type, size, path in symbols:
|
| - if symbol_type in ('b', 'w'):
|
| - continue # skip bss and weak symbols
|
| - if path is None:
|
| - path = ''
|
| - entry = {'size': FormatBytes(size),
|
| - 'symbol': sym,
|
| - 'type': SymbolTypeToHuman(symbol_type),
|
| - 'location': path }
|
| - out.write(json.dumps(entry))
|
| - out.write(',\n')
|
| - dumped += 1
|
| - if dumped >= n:
|
| - return
|
| - finally:
|
| - out.write('];\n')
|
| - out.flush()
|
| - out.close()
|
| -
|
| -
|
| def MakeSourceMap(symbols):
|
| sources = {}
|
| for _sym, _symbol_type, size, path in symbols:
|
| @@ -418,55 +245,6 @@ def MakeSourceMap(symbols):
|
| return sources
|
|
|
|
|
| -# TODO(andrewhayden): Only used for legacy reports. Delete.
|
| -def DumpLargestSources(symbols, outfile, n):
|
| - source_map = MakeSourceMap(symbols)
|
| - sources = sorted(source_map.values(), key=lambda x: -x['size'])
|
| - dumped = 0
|
| - out = open(outfile, 'w')
|
| - try:
|
| - out.write('var largestSources = [\n')
|
| - for record in sources:
|
| - entry = {'size': FormatBytes(record['size']),
|
| - 'symbol_count': str(record['symbol_count']),
|
| - 'location': record['path']}
|
| - out.write(json.dumps(entry))
|
| - out.write(',\n')
|
| - dumped += 1
|
| - if dumped >= n:
|
| - return
|
| - finally:
|
| - out.write('];\n')
|
| - out.flush()
|
| - out.close()
|
| -
|
| -
|
| -# TODO(andrewhayden): Only used for legacy reports. Delete.
|
| -def DumpLargestVTables(symbols, outfile, n):
|
| - vtables = []
|
| - for symbol, _type, size, path in symbols:
|
| - if 'vtable for ' in symbol:
|
| - vtables.append({'symbol': symbol, 'path': path, 'size': size})
|
| - vtables = sorted(vtables, key=lambda x: -x['size'])
|
| - dumped = 0
|
| - out = open(outfile, 'w')
|
| - try:
|
| - out.write('var largestVTables = [\n')
|
| - for record in vtables:
|
| - entry = {'size': FormatBytes(record['size']),
|
| - 'symbol': record['symbol'],
|
| - 'location': record['path']}
|
| - out.write(json.dumps(entry))
|
| - out.write(',\n')
|
| - dumped += 1
|
| - if dumped >= n:
|
| - return
|
| - finally:
|
| - out.write('];\n')
|
| - out.flush()
|
| - out.close()
|
| -
|
| -
|
| # Regex for parsing "nm" output. A sample line looks like this:
|
| # 0167b39c 00000018 t ACCESS_DESCRIPTION_free /path/file.c:95
|
| #
|
| @@ -886,44 +664,26 @@ def main():
|
| os.makedirs(opts.destdir, 0755)
|
|
|
|
|
| - if opts.legacy: # legacy report
|
| - DumpTreemap(symbols, os.path.join(opts.destdir, 'treemap-dump.js'))
|
| - DumpLargestSymbols(symbols,
|
| - os.path.join(opts.destdir, 'largest-symbols.js'), 100)
|
| - DumpLargestSources(symbols,
|
| - os.path.join(opts.destdir, 'largest-sources.js'), 100)
|
| - DumpLargestVTables(symbols,
|
| - os.path.join(opts.destdir, 'largest-vtables.js'), 100)
|
| - treemap_out = os.path.join(opts.destdir, 'webtreemap')
|
| - if not os.path.exists(treemap_out):
|
| - os.makedirs(treemap_out, 0755)
|
| - treemap_src = os.path.join('third_party', 'webtreemap', 'src')
|
| - shutil.copy(os.path.join(treemap_src, 'COPYING'), treemap_out)
|
| - shutil.copy(os.path.join(treemap_src, 'webtreemap.js'), treemap_out)
|
| - shutil.copy(os.path.join(treemap_src, 'webtreemap.css'), treemap_out)
|
| - shutil.copy(os.path.join('tools', 'binary_size', 'legacy_template',
|
| - 'index.html'), opts.destdir)
|
| - else: # modern report
|
| - if opts.library:
|
| - symbol_path_origin_dir = os.path.dirname(os.path.abspath(opts.library))
|
| - else:
|
| - # Just a guess. Hopefully all paths in the input file are absolute.
|
| - symbol_path_origin_dir = os.path.abspath(os.getcwd())
|
| - data_js_file_name = os.path.join(opts.destdir, 'data.js')
|
| - DumpCompactTree(symbols, symbol_path_origin_dir, data_js_file_name)
|
| - d3_out = os.path.join(opts.destdir, 'd3')
|
| - if not os.path.exists(d3_out):
|
| - os.makedirs(d3_out, 0755)
|
| - d3_src = os.path.join(os.path.dirname(__file__),
|
| - '..',
|
| - '..',
|
| - 'third_party', 'd3', 'src')
|
| - template_src = os.path.join(os.path.dirname(__file__),
|
| - 'template')
|
| - shutil.copy(os.path.join(d3_src, 'LICENSE'), d3_out)
|
| - shutil.copy(os.path.join(d3_src, 'd3.js'), d3_out)
|
| - shutil.copy(os.path.join(template_src, 'index.html'), opts.destdir)
|
| - shutil.copy(os.path.join(template_src, 'D3SymbolTreeMap.js'), opts.destdir)
|
| + if opts.library:
|
| + symbol_path_origin_dir = os.path.dirname(os.path.abspath(opts.library))
|
| + else:
|
| + # Just a guess. Hopefully all paths in the input file are absolute.
|
| + symbol_path_origin_dir = os.path.abspath(os.getcwd())
|
| + data_js_file_name = os.path.join(opts.destdir, 'data.js')
|
| + DumpCompactTree(symbols, symbol_path_origin_dir, data_js_file_name)
|
| + d3_out = os.path.join(opts.destdir, 'd3')
|
| + if not os.path.exists(d3_out):
|
| + os.makedirs(d3_out, 0755)
|
| + d3_src = os.path.join(os.path.dirname(__file__),
|
| + '..',
|
| + '..',
|
| + 'third_party', 'd3', 'src')
|
| + template_src = os.path.join(os.path.dirname(__file__),
|
| + 'template')
|
| + shutil.copy(os.path.join(d3_src, 'LICENSE'), d3_out)
|
| + shutil.copy(os.path.join(d3_src, 'd3.js'), d3_out)
|
| + shutil.copy(os.path.join(template_src, 'index.html'), opts.destdir)
|
| + shutil.copy(os.path.join(template_src, 'D3SymbolTreeMap.js'), opts.destdir)
|
|
|
| print 'Report saved to ' + opts.destdir + '/index.html'
|
|
|
|
|