xref: /aosp_15_r20/external/skia/infra/bots/buildstats/buildstats_flutter.py (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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