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