15PYTHON_VERSION_COMPATIBILITY =
"PY3"
20 'recipe_engine/context',
26 'recipe_engine/properties',
27 'recipe_engine/raw_io',
32SEEK_TRACE_NAME =
'skottie::Animation::seek'
33RENDER_TRACE_NAME =
'skottie::Animation::render'
34EXPECTED_DM_FRAMES = 25
38 """Run DM on lottie files with tracing turned on and then parse the output."""
39 api.flavor.create_clean_device_dir(
40 api.flavor.device_dirs.dm_dir)
41 lotties_host = api.path.start_dir.join(
'lotties_with_assets')
42 lotties_device = api.path.start_dir.join(
'lotties_with_assets')
43 if 'Android' in api.vars.builder_cfg.get(
'extra_config'):
49 lotties_device = api.flavor.device_path_join(api.flavor.device_dirs.tmp_dir,
'lotties_with_assets')
50 api.flavor.create_clean_device_dir(lotties_device)
53 lotties_no_symlinks = api.path.mkdtemp(
'lwa').
join(
'nosymlinks')
54 api.file.copytree(
'Copying files on host to remove symlinks', lotties_host, lotties_no_symlinks)
55 lotties_host = lotties_no_symlinks
56 api.flavor.copy_directory_contents_to_device(lotties_host, lotties_device)
60 lottie_files = api.file.listdir(
61 'list lottie files', lotties_host,
62 test_data=[
'skottie_asset_000',
'skottie_asset_001',
'skottie_asset_002'])
65 for idx, lottie_file
in enumerate(lottie_files):
66 lottie_name = api.path.basename(lottie_file)
67 lottie_folder = api.flavor.device_path_join(lotties_device, lottie_name)
69 trace_output_path = api.flavor.device_path_join(
70 api.flavor.device_dirs.dm_dir,
'%s.json' % (idx + 1))
74 '--resourcePath', api.flavor.device_dirs.resource_dir,
75 '--lotties', lottie_folder,
79 '--traceMatch',
'skottie',
80 '--trace', trace_output_path,
82 'data.json',
'Android' in api.properties[
'buildername']),
84 if api.vars.builder_cfg.get(
'cpu_or_gpu') ==
'GPU':
85 dm_args.extend([
'--config',
'gles',
'--nocpu'])
86 elif api.vars.builder_cfg.get(
'cpu_or_gpu') ==
'CPU':
87 dm_args.extend([
'--config',
'8888',
'--nogpu'])
88 api.run(api.flavor.step,
'dm', cmd=dm_args, abort_on_failure=
False)
90 trace_test_data = api.properties.get(
'trace_test_data',
'{}')
91 trace_file_content = api.flavor.read_file_on_device(trace_output_path)
92 if not trace_file_content
and trace_test_data:
93 trace_file_content = trace_test_data
96 if api.vars.builder_cfg.get(
'cpu_or_gpu') ==
'CPU':
98 perf_results[lottie_name] = {
99 key:
parse_trace(trace_file_content, lottie_name, api),
101 api.flavor.remove_file_on_device(trace_output_path)
105 'gitHash': api.properties[
'revision'],
106 'swarming_bot_id': api.vars.swarming_bot_id,
107 'swarming_task_id': api.vars.swarming_task_id,
108 'renderer':
'skottie',
110 'bench_type':
'tracing',
111 'source_type':
'skottie',
113 'results': perf_results,
115 if api.vars.is_trybot:
116 perf_json[
'issue'] = api.vars.issue
117 perf_json[
'patchset'] = api.vars.patchset
118 perf_json[
'patch_storage'] = api.vars.patch_storage
120 reg = re.compile(
'Perf-(?P<os>[A-Za-z0-9_]+)-'
121 '(?P<compiler>[A-Za-z0-9_]+)-'
122 '(?P<model>[A-Za-z0-9_]+)-'
123 '(?P<cpu_or_gpu>[A-Z]+)-'
124 '(?P<cpu_or_gpu_value>[A-Za-z0-9_]+)-'
125 '(?P<arch>[A-Za-z0-9_]+)-'
126 '(?P<configuration>[A-Za-z0-9_]+)-'
127 'All(-(?P<extra_config>[A-Za-z0-9_]+)|)')
128 m = reg.match(api.properties[
'buildername'])
129 keys = [
'os',
'compiler',
'model',
'cpu_or_gpu',
'cpu_or_gpu_value',
'arch',
130 'configuration',
'extra_config']
132 perf_json[
'key'][k] = m.group(k)
135 api.file.ensure_directory(
137 api.flavor.host_dirs.perf_data_dir)
138 now = api.time.utcnow()
139 ts =
int(calendar.timegm(now.utctimetuple()))
140 json_path = api.flavor.host_dirs.perf_data_dir.join(
141 'perf_%s_%d.json' % (api.properties[
'revision'], ts))
142 json_contents = json.dumps(
143 perf_json, indent=4, sort_keys=
True, separators=(
',',
': '))
144 api.file.write_text(
'write output JSON', json_path, json_contents)
148 """Returns the DM regex to match the specified lottie file name."""
149 trace_match =
'^%s$' % lottie_filename
150 if is_android
and ' ' not in trace_match:
154 for sp_char
in string.punctuation:
158 trace_match = trace_match.replace(sp_char,
'\%s' % sp_char)
163 """parse_trace parses the specified trace JSON.
165 Parses the trace JSON and calculates the time of a single frame. Frame time
is
166 considered the same
as seek time + render time.
167 Note: The first seek
is ignored because it
is a constructor call.
169 A dictionary
is returned that has the following structure:
176 script = api.infra.resource('parse_skottie_trace.py')
177 step_result = api.run(
179 'parse %s trace' % lottie_filename,
180 cmd=[
'python3', script, trace_json, lottie_filename, api.json.output(),
181 SEEK_TRACE_NAME, RENDER_TRACE_NAME, EXPECTED_DM_FRAMES])
184 output = dict(step_result.json.output)
185 output[
'frame_max_us'] =
float(
"%.2f" % output[
'frame_max_us'])
186 output[
'frame_min_us'] =
float(
"%.2f" % output[
'frame_min_us'])
187 output[
'frame_avg_us'] =
float(
"%.2f" % output[
'frame_avg_us'])
193 api.file.ensure_directory(
'makedirs tmp_dir', api.vars.tmp_dir)
194 api.flavor.setup(
'dm')
198 api.flavor.install(resources=
True, lotties=
True)
201 api.flavor.cleanup_steps()
202 api.run.check_failure()
207[{"ph":"X","name":"void skottie::Animation::seek(SkScalar)","ts":452,"dur":2.57,"tid":1,"pid":0},{"ph":"X","name":"void SkCanvas::drawPaint(const SkPaint &)","ts":473,"dur":2.67e+03,"tid":1,"pid":0},{"ph":"X","name":"void skottie::Animation::seek(SkScalar)","ts":3.15e+03,"dur":2.25,"tid":1,"pid":0},{"ph":"X","name":"void skottie::Animation::render(SkCanvas *, const SkRect *, RenderFlags) const","ts":3.15e+03,"dur":216,"tid":1,"pid":0},{"ph":"X","name":"void SkCanvas::drawPath(const SkPath &, const SkPaint &)","ts":3.35e+03,"dur":15.1,"tid":1,"pid":0},{"ph":"X","name":"void skottie::Animation::seek(SkScalar)","ts":3.37e+03,"dur":1.17,"tid":1,"pid":0},{"ph":"X","name":"void skottie::Animation::render(SkCanvas *, const SkRect *, RenderFlags) const","ts":3.37e+03,"dur":140,"tid":1,"pid":0}]
209 dm_json_test_data =
"""
211 "gitHash":
"bac53f089dbc473862bc5a2e328ba7600e0ed9c4",
212 "swarming_bot_id":
"skia-rpi-094",
213 "swarming_task_id":
"438f11c0e19eab11",
218 "cpu_or_gpu_value":
"Mali400MP2",
219 "extra_config":
"Android",
220 "model":
"AndroidOne",
228 'frame_avg_us': 179.71,
229 'frame_min_us': 141.17,
230 'frame_max_us': 218.25
232 android_buildername = (
'Perf-Android-Clang-AndroidOne-GPU-Mali400MP2-arm-'
233 'Release-All-Android_SkottieTracing')
234 gpu_buildername = (
'Perf-Debian10-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-'
235 'Release-All-SkottieTracing')
236 cpu_buildername = (
'Perf-Debian10-Clang-GCE-CPU-AVX2-x86_64-Release-All-'
239 api.test(android_buildername) +
240 api.properties(buildername=android_buildername,
241 repository=
'https://skia.googlesource.com/skia.git',
244 trace_test_data=trace_output,
245 dm_json_test_data=dm_json_test_data,
246 path_config=
'kitchen',
247 swarm_out_dir=
'[SWARM_OUT_DIR]') +
248 api.step_data(
'parse skottie_asset_000 trace',
249 api.json.output(parse_trace_json)) +
250 api.step_data(
'parse skottie_asset_001 trace',
251 api.json.output(parse_trace_json)) +
252 api.step_data(
'parse skottie_asset_002 trace',
253 api.json.output(parse_trace_json))
256 api.test(gpu_buildername) +
257 api.properties(buildername=gpu_buildername,
258 repository=
'https://skia.googlesource.com/skia.git',
261 trace_test_data=trace_output,
262 dm_json_test_data=dm_json_test_data,
263 path_config=
'kitchen',
264 swarm_out_dir=
'[SWARM_OUT_DIR]') +
265 api.step_data(
'parse skottie_asset_000 trace',
266 api.json.output(parse_trace_json)) +
267 api.step_data(
'parse skottie_asset_001 trace',
268 api.json.output(parse_trace_json)) +
269 api.step_data(
'parse skottie_asset_002 trace',
270 api.json.output(parse_trace_json))
273 api.test(cpu_buildername) +
274 api.properties(buildername=cpu_buildername,
275 repository=
'https://skia.googlesource.com/skia.git',
278 trace_test_data=trace_output,
279 dm_json_test_data=dm_json_test_data,
280 path_config=
'kitchen',
281 swarm_out_dir=
'[SWARM_OUT_DIR]') +
282 api.step_data(
'parse skottie_asset_000 trace',
283 api.json.output(parse_trace_json)) +
284 api.step_data(
'parse skottie_asset_001 trace',
285 api.json.output(parse_trace_json)) +
286 api.step_data(
'parse skottie_asset_002 trace',
287 api.json.output(parse_trace_json))
290 api.test(
'skottietracing_parse_trace_error') +
291 api.properties(buildername=android_buildername,
292 repository=
'https://skia.googlesource.com/skia.git',
295 trace_test_data=trace_output,
296 dm_json_test_data=dm_json_test_data,
297 path_config=
'kitchen',
298 swarm_out_dir=
'[SWARM_OUT_DIR]') +
299 api.step_data(
'parse skottie_asset_000 trace',
300 api.json.output(parse_trace_json), retcode=1)
303 api.test(
'skottietracing_trybot') +
304 api.properties(buildername=android_buildername,
305 repository=
'https://skia.googlesource.com/skia.git',
308 trace_test_data=trace_output,
309 dm_json_test_data=dm_json_test_data,
310 path_config=
'kitchen',
311 swarm_out_dir=
'[SWARM_OUT_DIR]',
312 patch_ref=
'89/456789/12',
313 patch_repo=
'https://skia.googlesource.com/skia.git',
314 patch_storage=
'gerrit',
317 gerrit_project=
'skia',
318 gerrit_url=
'https://skia-review.googlesource.com/') +
319 api.step_data(
'parse skottie_asset_000 trace',
320 api.json.output(parse_trace_json)) +
321 api.step_data(
'parse skottie_asset_001 trace',
322 api.json.output(parse_trace_json)) +
323 api.step_data(
'parse skottie_asset_002 trace',
324 api.json.output(parse_trace_json))
def get_trace_match(lottie_filename, is_android)
def parse_trace(trace_json, lottie_filename, api)
static SkString join(const CommandLineFlags::StringArray &)