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 config = sys.argv[7] 27 total_size_bytes_key = sys.argv[8] 28 lib_name = sys.argv[9] 29 magic_seperator = sys.argv[10] 30 31 results = { 32 'key': { }, 33 'results': { } 34 } 35 36 props = propstr.split(' ') 37 for i in range(0, len(props), 2): 38 results[props[i]] = props[i+1] 39 40 keys = keystr.split(' ') 41 for i in range(0, len(keys), 2): 42 results['key'][keys[i]] = keys[i+1] 43 44 # Human "readable" reports as an FYI. 45 print(magic_seperator) 46 print('Report by file, then by symbol with ellided/combined templates') 47 lines = subprocess.check_output([bloaty_path, stripped_file, 48 '-d', 'compileunits,symbols', '-s', 'file', 49 '-n', '0', '--tsv', '--demangle=short', 50 '--debug-file=%s' % symbols_file], 51 encoding='utf-8') 52 grand_total = print_skia_lines_file_symbol(lines) 53 print(magic_seperator) 54 print('Report by file, then by symbol with full templates') 55 lines = subprocess.check_output([bloaty_path, stripped_file, 56 '-d', 'compileunits,symbols', '-s', 'file', 57 '-n', '0', '--tsv', '--demangle=full', 58 '--debug-file=%s' % symbols_file], 59 encoding='utf-8') 60 print_skia_lines_file_symbol(lines) 61 print(magic_seperator) 62 63 print('Report by symbol, then by file with ellided/combined templates') 64 lines = subprocess.check_output([bloaty_path, stripped_file, 65 '-d', 'symbols,compileunits', '-s', 'file', 66 '-n', '0', '--tsv', '--demangle=short', 67 '--debug-file=%s' % symbols_file], 68 encoding='utf-8') 69 print_skia_lines_symbol_file(lines) 70 print(magic_seperator) 71 72 print('Report by symbol, then by file with full templates') 73 lines = subprocess.check_output([bloaty_path, stripped_file, 74 '-d', 'symbols,compileunits', '-s', 'file', 75 '-n', '0', '--tsv', '--demangle=full', 76 '--debug-file=%s' % symbols_file], 77 encoding='utf-8') 78 print_skia_lines_symbol_file(lines) 79 print(magic_seperator) 80 81 r = { 82 # Use the default config as stats about the whole binary 83 config : { 84 total_size_bytes_key: grand_total 85 }, 86 } 87 88 results['results'][lib_name] = r 89 90 # Make debugging easier 91 print(json.dumps(results, indent=2)) 92 93 with open(os.path.join(out_dir, lib_name+'.json'), 'w') as output: 94 output.write(json.dumps(results, indent=2)) 95 96 97def bytes_or_kb(num): 98 if num < 1024: 99 return '%d bytes' % num 100 else: 101 return '%1.1f KiB' % (num / 1024.0) 102 103 104def print_skia_lines_file_symbol(lines): 105 lines = lines.split('\n') 106 grand_total = 0 107 sub_total = 0 108 cur_file = '' 109 110 for line in lines: 111 # Line looks like: 112 # ../../third_party/skia/src/file.cpp\tSkTSect<>::intersects()\t1224\t1348 113 parts = line.split('\t') 114 if len(parts) != 4: 115 continue 116 this_file = parts[0] 117 if 'third_party/skia' not in this_file: 118 continue 119 symbol = parts[1] 120 if '.debug' in symbol: 121 continue 122 # vmsize = parts[2] Not needed 123 filesize = int(parts[3]) 124 125 if this_file != cur_file: 126 if cur_file != '': 127 print('\t%-100s: %s' % ('Total File Size', bytes_or_kb(sub_total))) 128 sub_total = 0 129 cur_file = this_file 130 print(this_file.replace('../../third_party/skia', 'skia')) 131 132 print('\t%-100s: %s' % (symbol, bytes_or_kb(filesize))) 133 sub_total += filesize 134 grand_total += filesize 135 136 print('\t%-100s: %s' % ('Total File Size', bytes_or_kb(sub_total))) 137 print('=======================================') 138 print('Grand Total File Size: %s' % bytes_or_kb(grand_total)) 139 return grand_total 140 141 142def print_skia_lines_symbol_file(lines): 143 lines = lines.split('\n') 144 145 for line in lines: 146 # Line looks like: 147 # SkTSect<>::intersects()\t../../third_party/skia/src/file.cpp\t1224\t1348 148 parts = line.split('\t') 149 if len(parts) != 4: 150 continue 151 symbol = parts[0] 152 if 'section' in symbol: 153 continue 154 this_file = parts[1] 155 if 'third_party/skia' not in this_file: 156 continue 157 this_file = this_file.replace('../../third_party/skia', 'skia') 158 # vmsize = parts[2] Not needed 159 filesize = int(parts[3]) 160 161 print('%-10s: %-80s in %s' % (bytes_or_kb(filesize), symbol, this_file)) 162 163 164if __name__ == '__main__': 165 main() 166