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