| OLD | NEW | 
|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python | 
| 2 # Copyright 2014 The Chromium Authors. All rights reserved. | 2 # Copyright 2014 The Chromium Authors. All rights reserved. | 
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be | 
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. | 
| 5 | 5 | 
| 6 """Generate a spatial analysis against an arbitrary library. | 6 """Generate a spatial analysis against an arbitrary library. | 
| 7 | 7 | 
| 8 To use, build the 'binary_size_tool' target. Then run this tool, passing | 8 To use, build the 'binary_size_tool' target. Then run this tool, passing | 
| 9 in the location of the library to be analyzed along with any other options | 9 in the location of the library to be analyzed along with any other options | 
| 10 you desire. | 10 you desire. | 
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 162   return 2  # Depth of the added subtree. | 162   return 2  # Depth of the added subtree. | 
| 163 | 163 | 
| 164 | 164 | 
| 165 def MakeCompactTree(symbols, symbol_path_origin_dir): | 165 def MakeCompactTree(symbols, symbol_path_origin_dir): | 
| 166   result = {NODE_NAME_KEY: '/', | 166   result = {NODE_NAME_KEY: '/', | 
| 167             NODE_CHILDREN_KEY: {}, | 167             NODE_CHILDREN_KEY: {}, | 
| 168             NODE_TYPE_KEY: 'p', | 168             NODE_TYPE_KEY: 'p', | 
| 169             NODE_MAX_DEPTH_KEY: 0} | 169             NODE_MAX_DEPTH_KEY: 0} | 
| 170   seen_symbol_with_path = False | 170   seen_symbol_with_path = False | 
| 171   cwd = os.path.abspath(os.getcwd()) | 171   cwd = os.path.abspath(os.getcwd()) | 
| 172   for symbol_name, symbol_type, symbol_size, file_path in symbols: | 172   for symbol_name, symbol_type, symbol_size, file_path, _address in symbols: | 
| 173 | 173 | 
| 174     if 'vtable for ' in symbol_name: | 174     if 'vtable for ' in symbol_name: | 
| 175       symbol_type = '@'  # hack to categorize these separately | 175       symbol_type = '@'  # hack to categorize these separately | 
| 176     # Take path like '/foo/bar/baz', convert to ['foo', 'bar', 'baz'] | 176     # Take path like '/foo/bar/baz', convert to ['foo', 'bar', 'baz'] | 
| 177     if file_path and file_path != "??": | 177     if file_path and file_path != "??": | 
| 178       file_path = os.path.abspath(os.path.join(symbol_path_origin_dir, | 178       file_path = os.path.abspath(os.path.join(symbol_path_origin_dir, | 
| 179                                                file_path)) | 179                                                file_path)) | 
| 180       # Let the output structure be relative to $CWD if inside $CWD, | 180       # Let the output structure be relative to $CWD if inside $CWD, | 
| 181       # otherwise relative to the disk root. This is to avoid | 181       # otherwise relative to the disk root. This is to avoid | 
| 182       # unnecessary click-through levels in the output. | 182       # unnecessary click-through levels in the output. | 
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 238                  directory or file names) and whose values are other nodes; | 238                  directory or file names) and whose values are other nodes; | 
| 239        size:     the total size, in bytes, of all the leaf nodes that are | 239        size:     the total size, in bytes, of all the leaf nodes that are | 
| 240                  contained within the children dict (recursively expanded) | 240                  contained within the children dict (recursively expanded) | 
| 241 | 241 | 
| 242   The result object is itself a dictionary that represents the common ancestor | 242   The result object is itself a dictionary that represents the common ancestor | 
| 243   of all child nodes, e.g. a path to which all other nodes beneath it are | 243   of all child nodes, e.g. a path to which all other nodes beneath it are | 
| 244   relative. The 'size' attribute of this dict yields the sum of the size of all | 244   relative. The 'size' attribute of this dict yields the sum of the size of all | 
| 245   leaf nodes within the data structure. | 245   leaf nodes within the data structure. | 
| 246   """ | 246   """ | 
| 247   dirs = {'children': {}, 'size': 0} | 247   dirs = {'children': {}, 'size': 0} | 
| 248   for sym, symbol_type, size, path in symbols: | 248   for sym, symbol_type, size, path, _address in symbols: | 
| 249     dirs['size'] += size | 249     dirs['size'] += size | 
| 250     if path: | 250     if path: | 
| 251       path = os.path.normpath(path) | 251       path = os.path.normpath(path) | 
| 252       if path.startswith('/'): | 252       if path.startswith('/'): | 
| 253         path = path[1:] | 253         path = path[1:] | 
| 254 | 254 | 
| 255     parts = None | 255     parts = None | 
| 256     if path: | 256     if path: | 
| 257       parts = path.split('/') | 257       parts = path.split('/') | 
| 258 | 258 | 
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 375 | 375 | 
| 376 | 376 | 
| 377 # TODO(andrewhayden): Only used for legacy reports. Delete. | 377 # TODO(andrewhayden): Only used for legacy reports. Delete. | 
| 378 def DumpLargestSymbols(symbols, outfile, n): | 378 def DumpLargestSymbols(symbols, outfile, n): | 
| 379   # a list of (sym, symbol_type, size, path); sort by size. | 379   # a list of (sym, symbol_type, size, path); sort by size. | 
| 380   symbols = sorted(symbols, key=lambda x: -x[2]) | 380   symbols = sorted(symbols, key=lambda x: -x[2]) | 
| 381   dumped = 0 | 381   dumped = 0 | 
| 382   out = open(outfile, 'w') | 382   out = open(outfile, 'w') | 
| 383   try: | 383   try: | 
| 384     out.write('var largestSymbols = [\n') | 384     out.write('var largestSymbols = [\n') | 
| 385     for sym, symbol_type, size, path in symbols: | 385     for sym, symbol_type, size, path, _address in symbols: | 
| 386       if symbol_type in ('b', 'w'): | 386       if symbol_type in ('b', 'w'): | 
| 387         continue  # skip bss and weak symbols | 387         continue  # skip bss and weak symbols | 
| 388       if path is None: | 388       if path is None: | 
| 389         path = '' | 389         path = '' | 
| 390       entry = {'size': FormatBytes(size), | 390       entry = {'size': FormatBytes(size), | 
| 391                'symbol': sym, | 391                'symbol': sym, | 
| 392                'type': SymbolTypeToHuman(symbol_type), | 392                'type': SymbolTypeToHuman(symbol_type), | 
| 393                'location': path } | 393                'location': path } | 
| 394       out.write(json.dumps(entry)) | 394       out.write(json.dumps(entry)) | 
| 395       out.write(',\n') | 395       out.write(',\n') | 
| 396       dumped += 1 | 396       dumped += 1 | 
| 397       if dumped >= n: | 397       if dumped >= n: | 
| 398         return | 398         return | 
| 399   finally: | 399   finally: | 
| 400     out.write('];\n') | 400     out.write('];\n') | 
| 401     out.flush() | 401     out.flush() | 
| 402     out.close() | 402     out.close() | 
| 403 | 403 | 
| 404 | 404 | 
| 405 def MakeSourceMap(symbols): | 405 def MakeSourceMap(symbols): | 
| 406   sources = {} | 406   sources = {} | 
| 407   for _sym, _symbol_type, size, path in symbols: | 407   for _sym, _symbol_type, size, path, _address in symbols: | 
| 408     key = None | 408     key = None | 
| 409     if path: | 409     if path: | 
| 410       key = os.path.normpath(path) | 410       key = os.path.normpath(path) | 
| 411     else: | 411     else: | 
| 412       key = '[no path]' | 412       key = '[no path]' | 
| 413     if key not in sources: | 413     if key not in sources: | 
| 414       sources[key] = {'path': path, 'symbol_count': 0, 'size': 0} | 414       sources[key] = {'path': path, 'symbol_count': 0, 'size': 0} | 
| 415     record = sources[key] | 415     record = sources[key] | 
| 416     record['size'] += size | 416     record['size'] += size | 
| 417     record['symbol_count'] += 1 | 417     record['symbol_count'] += 1 | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
| 437         return | 437         return | 
| 438   finally: | 438   finally: | 
| 439     out.write('];\n') | 439     out.write('];\n') | 
| 440     out.flush() | 440     out.flush() | 
| 441     out.close() | 441     out.close() | 
| 442 | 442 | 
| 443 | 443 | 
| 444 # TODO(andrewhayden): Only used for legacy reports. Delete. | 444 # TODO(andrewhayden): Only used for legacy reports. Delete. | 
| 445 def DumpLargestVTables(symbols, outfile, n): | 445 def DumpLargestVTables(symbols, outfile, n): | 
| 446   vtables = [] | 446   vtables = [] | 
| 447   for symbol, _type, size, path in symbols: | 447   for symbol, _type, size, path, _address in symbols: | 
| 448     if 'vtable for ' in symbol: | 448     if 'vtable for ' in symbol: | 
| 449       vtables.append({'symbol': symbol, 'path': path, 'size': size}) | 449       vtables.append({'symbol': symbol, 'path': path, 'size': size}) | 
| 450   vtables = sorted(vtables, key=lambda x: -x['size']) | 450   vtables = sorted(vtables, key=lambda x: -x['size']) | 
| 451   dumped = 0 | 451   dumped = 0 | 
| 452   out = open(outfile, 'w') | 452   out = open(outfile, 'w') | 
| 453   try: | 453   try: | 
| 454     out.write('var largestVTables = [\n') | 454     out.write('var largestVTables = [\n') | 
| 455     for record in vtables: | 455     for record in vtables: | 
| 456       entry = {'size': FormatBytes(record['size']), | 456       entry = {'size': FormatBytes(record['size']), | 
| 457                'symbol': record['symbol'], | 457                'symbol': record['symbol'], | 
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 923     shutil.copy(os.path.join(d3_src, 'LICENSE'), d3_out) | 923     shutil.copy(os.path.join(d3_src, 'LICENSE'), d3_out) | 
| 924     shutil.copy(os.path.join(d3_src, 'd3.js'), d3_out) | 924     shutil.copy(os.path.join(d3_src, 'd3.js'), d3_out) | 
| 925     shutil.copy(os.path.join(template_src, 'index.html'), opts.destdir) | 925     shutil.copy(os.path.join(template_src, 'index.html'), opts.destdir) | 
| 926     shutil.copy(os.path.join(template_src, 'D3SymbolTreeMap.js'), opts.destdir) | 926     shutil.copy(os.path.join(template_src, 'D3SymbolTreeMap.js'), opts.destdir) | 
| 927 | 927 | 
| 928   print 'Report saved to ' + opts.destdir + '/index.html' | 928   print 'Report saved to ' + opts.destdir + '/index.html' | 
| 929 | 929 | 
| 930 | 930 | 
| 931 if __name__ == '__main__': | 931 if __name__ == '__main__': | 
| 932   sys.exit(main()) | 932   sys.exit(main()) | 
| OLD | NEW | 
|---|