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