1# Copyright 2018 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5 6"""Writes a Perf-formated json file with stats about Skia's size in flutter.""" 7 8 9import json 10import os 11import subprocess 12import sys 13 14 15def main(): 16 # This should be the stripped file from 17 # out/android_release/lib.stripped/libflutter.so 18 stripped_file = sys.argv[1] 19 out_dir = sys.argv[2] 20 keystr = sys.argv[3] 21 propstr = sys.argv[4] 22 bloaty_path = sys.argv[5] 23 # This is the unstripped out/android_release/libflutter.so 24 # The symbols in it are needed to get the compileunits data. 25 symbols_file = sys.argv[6] 26 27 results = { 28 'key': { }, 29 'results': { } 30 } 31 32 props = propstr.split(' ') 33 for i in range(0, len(props), 2): 34 results[props[i]] = props[i+1] 35 36 keys = keystr.split(' ') 37 for i in range(0, len(keys), 2): 38 results['key'][keys[i]] = keys[i+1] 39 40 magic_seperator = '#$%^&*' 41 42 # Human "readable" reports as an FYI. 43 print magic_seperator 44 print 'Report by file, then by symbol with ellided/combined templates' 45 lines = subprocess.check_output([bloaty_path, stripped_file, 46 '-d', 'compileunits,symbols', '-s', 'file', 47 '-n', '0', '--tsv', '--demangle=short', 48 '--debug-file=%s' % symbols_file]) 49 grand_total = print_skia_lines_file_symbol(lines) 50 print magic_seperator 51 print 'Report by file, then by symbol with full templates' 52 lines = subprocess.check_output([bloaty_path, stripped_file, 53 '-d', 'compileunits,symbols', '-s', 'file', 54 '-n', '0', '--tsv', '--demangle=full', 55 '--debug-file=%s' % symbols_file]) 56 print_skia_lines_file_symbol(lines) 57 print magic_seperator 58 59 print 'Report by symbol, then by file with ellided/combined templates' 60 lines = subprocess.check_output([bloaty_path, stripped_file, 61 '-d', 'symbols,compileunits', '-s', 'file', 62 '-n', '0', '--tsv', '--demangle=short', 63 '--debug-file=%s' % symbols_file]) 64 print_skia_lines_symbol_file(lines) 65 print magic_seperator 66 67 print 'Report by symbol, then by file with full templates' 68 lines = subprocess.check_output([bloaty_path, stripped_file, 69 '-d', 'symbols,compileunits', '-s', 'file', 70 '-n', '0', '--tsv', '--demangle=full', 71 '--debug-file=%s' % symbols_file]) 72 print_skia_lines_symbol_file(lines) 73 print magic_seperator 74 75 r = { 76 # Use the default config as stats about the whole binary 77 'skia_in_flutter' : { 78 'total_size_bytes': grand_total 79 }, 80 } 81 82 name = 'libflutter.so' 83 results['results'][name] = r 84 85 # Make debugging easier 86 print json.dumps(results, indent=2) 87 88 with open(os.path.join(out_dir, name+'.json'), 'w') as output: 89 output.write(json.dumps(results, indent=2)) 90 91 92def bytes_or_kb(num): 93 if num < 1024: 94 return '%d bytes' % num 95 else: 96 return '%1.1f KiB' % (num / 1024.0) 97 98 99def print_skia_lines_file_symbol(lines): 100 lines = lines.split('\n') 101 grand_total = 0 102 sub_total = 0 103 cur_file = '' 104 105 for line in lines: 106 # Line looks like: 107 # ../../third_party/skia/src/file.cpp\tSkTSect<>::intersects()\t1224\t1348 108 parts = line.split('\t') 109 if len(parts) != 4: 110 continue 111 this_file = parts[0] 112 if 'third_party/skia' not in this_file: 113 continue 114 symbol = parts[1] 115 if '.debug' in symbol: 116 continue 117 # vmsize = parts[2] Not needed 118 filesize = int(parts[3]) 119 120 if this_file != cur_file: 121 if cur_file != '': 122 print '\t%-100s: %s' % ('Total File Size', bytes_or_kb(sub_total)) 123 sub_total = 0 124 cur_file = this_file 125 print this_file.replace('../../third_party/skia', 'skia') 126 127 print '\t%-100s: %s' % (symbol, bytes_or_kb(filesize)) 128 sub_total += filesize 129 grand_total += filesize 130 131 print '\t%-100s: %s' % ('Total File Size', bytes_or_kb(sub_total)) 132 print '=======================================' 133 print 'Grand Total File Size: %s' % bytes_or_kb(grand_total) 134 return grand_total 135 136 137def print_skia_lines_symbol_file(lines): 138 lines = lines.split('\n') 139 140 for line in lines: 141 # Line looks like: 142 # SkTSect<>::intersects()\t../../third_party/skia/src/file.cpp\t1224\t1348 143 parts = line.split('\t') 144 if len(parts) != 4: 145 continue 146 symbol = parts[0] 147 if 'section' in symbol: 148 continue 149 this_file = parts[1] 150 if 'third_party/skia' not in this_file: 151 continue 152 this_file = this_file.replace('../../third_party/skia', 'skia') 153 # vmsize = parts[2] Not needed 154 filesize = int(parts[3]) 155 156 print '%-10s: %-80s in %s' % (bytes_or_kb(filesize), symbol, this_file) 157 158 159if __name__ == '__main__': 160 main() 161