• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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# Recipe which analyzes a compiled binary for information (e.g. file size)
6
7DEPS = [
8  'checkout',
9  'recipe_engine/context',
10  'recipe_engine/file',
11  'recipe_engine/path',
12  'recipe_engine/properties',
13  'recipe_engine/python',
14  'recipe_engine/raw_io',
15  'recipe_engine/step',
16  'run',
17  'vars',
18]
19
20def RunSteps(api):
21  api.vars.setup()
22
23  checkout_root = api.checkout.default_checkout_root
24  api.checkout.bot_update(checkout_root=checkout_root)
25
26  out_dir = api.vars.swarming_out_dir
27  # Any binaries to scan should be here.
28  bin_dir = api.vars.build_dir
29
30  api.file.ensure_directory('mkdirs out_dir', out_dir, mode=0777)
31
32  analyzed = 0
33  with api.context(cwd=bin_dir):
34    files = api.file.glob_paths(
35        'find WASM binaries',
36        bin_dir,
37        '*.wasm',
38        test_data=['pathkit.wasm'])
39    analyzed += len(files)
40    if len(files):
41      analyze_wasm_file(api, checkout_root, out_dir, files)
42
43    files = api.file.glob_paths(
44        'find JS files',
45        bin_dir,
46        '*.js',
47        test_data=['pathkit.js'])
48    analyzed += len(files)
49    if len(files):
50      analyze_web_file(api, checkout_root, out_dir, files)
51
52    files = api.file.glob_paths(
53        'find JS mem files',
54        bin_dir,
55        '*.js.mem',
56        test_data=['pathkit.js.mem'])
57    analyzed += len(files)
58    if len(files):
59      analyze_web_file(api, checkout_root, out_dir, files)
60
61    files = api.file.glob_paths(
62        'find flutter library',
63        bin_dir,
64        'libflutter.so',
65        test_data=['libflutter.so'])
66    analyzed += len(files)
67    if len(files):
68      analyze_flutter_lib(api, checkout_root, out_dir, files)
69
70    files = api.file.glob_paths(
71        'find skia library',
72        bin_dir,
73        'libskia.so',
74        test_data=['libskia.so'])
75    analyzed += len(files)
76    if len(files):
77      analyze_cpp_lib(api, checkout_root, out_dir, files)
78  if not analyzed: # pragma: nocover
79    raise Exception('No files were analyzed!')
80
81
82def keys_and_props(api):
83  keys = []
84  keys_blacklist = ['role']
85  for k in sorted(api.vars.builder_cfg.keys()):
86      if not k in keys_blacklist:
87        keys.extend([k, api.vars.builder_cfg[k]])
88  keystr = ' '.join(keys)
89
90  props = [
91    'gitHash', api.properties['revision'],
92    'swarming_bot_id', api.vars.swarming_bot_id,
93    'swarming_task_id', api.vars.swarming_task_id,
94  ]
95
96  if api.vars.is_trybot:
97    props.extend([
98      'issue',    str(api.vars.issue),
99      'patchset', str(api.vars.patchset),
100      'patch_storage', api.vars.patch_storage,
101    ])
102  propstr = ' '.join(props)
103  return (keystr, propstr)
104
105
106# Get the raw and gzipped size of the given file
107def analyze_web_file(api, checkout_root, out_dir, files):
108  (keystr, propstr) = keys_and_props(api)
109
110  for f in files:
111    skia_dir = checkout_root.join('skia')
112    with api.context(cwd=skia_dir):
113      script = skia_dir.join('infra', 'bots', 'buildstats',
114                             'buildstats_web.py')
115      api.run(api.python, 'Analyze %s' % f, script=script,
116          args=[f, out_dir, keystr, propstr])
117
118
119# Get the raw size and a few metrics from bloaty
120def analyze_cpp_lib(api, checkout_root, out_dir, files):
121  (keystr, propstr) = keys_and_props(api)
122  bloaty_exe = api.path['start_dir'].join('bloaty', 'bloaty')
123
124  for f in files:
125    skia_dir = checkout_root.join('skia')
126    with api.context(cwd=skia_dir):
127      script = skia_dir.join('infra', 'bots', 'buildstats',
128                             'buildstats_cpp.py')
129      api.run(api.python, 'Analyze %s' % f, script=script,
130          args=[f, out_dir, keystr, propstr, bloaty_exe])
131
132
133# Get the size of skia in flutter and a few metrics from bloaty
134def analyze_flutter_lib(api, checkout_root, out_dir, files):
135  (keystr, propstr) = keys_and_props(api)
136  bloaty_exe = api.path['start_dir'].join('bloaty', 'bloaty')
137
138  for f in files:
139
140    skia_dir = checkout_root.join('skia')
141    with api.context(cwd=skia_dir):
142      stripped = api.vars.build_dir.join('libflutter_stripped.so')
143      script = skia_dir.join('infra', 'bots', 'buildstats',
144                             'buildstats_flutter.py')
145      step_data = api.run(api.python, 'Analyze flutter', script=script,
146                         args=[stripped, out_dir, keystr, propstr, bloaty_exe,
147                               f],
148                         stdout=api.raw_io.output())
149      if step_data and step_data.stdout:
150        magic_seperator = '#$%^&*'
151        sections = step_data.stdout.split(magic_seperator)
152        result = api.step.active_result
153        logs = result.presentation.logs
154        # Skip section 0 because it's everything before first print,
155        # which is probably the empty string.
156        logs['bloaty_file_symbol_short'] = sections[1].split('\n')
157        logs['bloaty_file_symbol_full']  = sections[2].split('\n')
158        logs['bloaty_symbol_file_short'] = sections[3].split('\n')
159        logs['bloaty_symbol_file_full']  = sections[4].split('\n')
160        logs['perf_json'] = sections[5].split('\n')
161
162
163# Get the size of skia in flutter and a few metrics from bloaty
164def analyze_wasm_file(api, checkout_root, out_dir, files):
165  (keystr, propstr) = keys_and_props(api)
166  bloaty_exe = api.path['start_dir'].join('bloaty', 'bloaty')
167
168  for f in files:
169
170    skia_dir = checkout_root.join('skia')
171    with api.context(cwd=skia_dir):
172      script = skia_dir.join('infra', 'bots', 'buildstats',
173                             'buildstats_wasm.py')
174      step_data = api.run(api.python, 'Analyze wasm', script=script,
175                         args=[f, out_dir, keystr, propstr, bloaty_exe],
176                         stdout=api.raw_io.output())
177      if step_data and step_data.stdout:
178        magic_seperator = '#$%^&*'
179        sections = step_data.stdout.split(magic_seperator)
180        result = api.step.active_result
181        logs = result.presentation.logs
182        # Skip section 0 because it's everything before first print,
183        # which is probably the empty string.
184        logs['bloaty_symbol_short'] = sections[1].split('\n')
185        logs['bloaty_symbol_full']  = sections[2].split('\n')
186        logs['perf_json']           = sections[3].split('\n')
187
188
189def GenTests(api):
190  builder = 'BuildStats-Debian9-EMCC-wasm-Release-PathKit'
191  yield (
192    api.test('normal_bot') +
193    api.properties(buildername=builder,
194                   repository='https://skia.googlesource.com/skia.git',
195                   revision='abc123',
196                   swarm_out_dir='[SWARM_OUT_DIR]',
197                   path_config='kitchen') +
198    api.step_data('get swarming bot id',
199        stdout=api.raw_io.output('skia-bot-123')) +
200    api.step_data('get swarming task id',
201        stdout=api.raw_io.output('123456abc')) +
202    api.step_data('Analyze wasm',
203        stdout=api.raw_io.output(sample_wasm)) +
204    api.step_data('Analyze flutter',
205          stdout=api.raw_io.output(sample_flutter))
206  )
207
208  yield (
209    api.test('trybot') +
210    api.properties(buildername=builder,
211                   repository='https://skia.googlesource.com/skia.git',
212                   revision='abc123',
213                   swarm_out_dir='[SWARM_OUT_DIR]',
214                   patch_repo='https://skia.googlesource.com/skia.git',
215                   path_config='kitchen') +
216    api.step_data('get swarming bot id',
217        stdout=api.raw_io.output('skia-bot-123')) +
218    api.step_data('get swarming task id',
219        stdout=api.raw_io.output('123456abc')) +
220    api.properties(patch_storage='gerrit') +
221    api.properties.tryserver(
222        buildername=builder,
223        gerrit_project='skia',
224        gerrit_url='https://skia-review.googlesource.com/',
225      ) +
226    api.step_data('Analyze wasm',
227        stdout=api.raw_io.output(sample_wasm)) +
228    api.step_data('Analyze flutter',
229          stdout=api.raw_io.output(sample_flutter))
230  )
231
232sample_wasm = """
233#$%^&*
234Report A
235    Total size: 50 bytes
236#$%^&*
237Report B
238    Total size: 60 bytes
239#$%^&*
240{
241  "some": "json"
242}
243"""
244
245sample_flutter = """
246#$%^&*
247Report A
248    Total size: 50 bytes
249#$%^&*
250Report B
251    Total size: 60 bytes
252#$%^&*
253Report C
254    Total size: 70 bytes
255#$%^&*
256Report D
257    Total size: 80 bytes
258#$%^&*
259{
260  "some": "json"
261}
262"""
263