1[
2  {
3    "cmd": [
4      "vpython",
5      "-u",
6      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
7      "--json-output",
8      "/path/to/tmp/json",
9      "listdir",
10      "[START_DIR]/lottie-samples"
11    ],
12    "infra_step": true,
13    "name": "list lottie files",
14    "~followup_annotations": [
15      "@@@STEP_LOG_LINE@listdir@[START_DIR]/lottie-samples/LICENSE@@@",
16      "@@@STEP_LOG_LINE@listdir@[START_DIR]/lottie-samples/lottie1.json@@@",
17      "@@@STEP_LOG_LINE@listdir@[START_DIR]/lottie-samples/lottie2.json@@@",
18      "@@@STEP_LOG_LINE@listdir@[START_DIR]/lottie-samples/lottie3.json@@@",
19      "@@@STEP_LOG_END@listdir@@@"
20    ]
21  },
22  {
23    "cmd": [
24      "npm",
25      "install"
26    ],
27    "cwd": "[START_DIR]/skia/tools/skottie-wasm-perf",
28    "env_prefixes": {
29      "PATH": [
30        "[START_DIR]/node/node/bin"
31      ]
32    },
33    "name": "npm install"
34  },
35  {
36    "cmd": [
37      "[START_DIR]/node/node/bin/node",
38      "[START_DIR]/skia/tools/skottie-wasm-perf/skottie-wasm-perf.js",
39      "--canvaskit_js",
40      "[START_DIR]/build/canvaskit.js",
41      "--canvaskit_wasm",
42      "[START_DIR]/build/canvaskit.wasm",
43      "--input",
44      "[START_DIR]/lottie-samples/lottie1.json",
45      "--output",
46      "[CLEANUP]/g3_try_tmp_1/lottie1.json"
47    ],
48    "cwd": "[START_DIR]/skia/tools/skottie-wasm-perf",
49    "env": {
50      "CHROME_HEADLESS": "1",
51      "DISPLAY": ":0",
52      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
53    },
54    "infra_step": true,
55    "name": "Run perf cmd line app"
56  },
57  {
58    "cmd": [
59      "python",
60      "-u",
61      "\nimport json\nimport sys\n\ntrace_output = sys.argv[1]\nwith open(trace_output, 'r') as f:\n  trace_json = json.load(f)\noutput_json_file = sys.argv[2]\nrenderer = sys.argv[3]  # Unused for now but might be useful in the future.\n\n# Output data about the GPU that was used.\nprint('GPU data:')\nprint(trace_json['metadata'].get('gpu-gl-renderer'))\nprint(trace_json['metadata'].get('gpu-driver'))\nprint(trace_json['metadata'].get('gpu-gl-vendor'))\n\nerroneous_termination_statuses = [\n    'replaced_by_new_reporter_at_same_stage',\n    'did_not_produce_frame',\n]\naccepted_termination_statuses = [\n    'missed_frame',\n    'submitted_frame',\n    'main_frame_aborted'\n]\n\ncurrent_frame_duration = 0\ntotal_frames = 0\nframe_id_to_start_ts = {}\n# Will contain tuples of frame_ids and their duration and status.\ncompleted_frame_id_and_duration_status = []\n# Will contain tuples of drawn frame_ids and their duration.\ndrawn_frame_id_and_duration = []\nfor trace in trace_json['traceEvents']:\n  if 'PipelineReporter' in trace['name']:\n    frame_id = trace['id']\n    args = trace.get('args')\n    if args and args.get('step') == 'BeginImplFrameToSendBeginMainFrame':\n      frame_id_to_start_ts[frame_id] = trace['ts']\n    elif args and (args.get('termination_status') in\n                   accepted_termination_statuses):\n      if not frame_id_to_start_ts.get(frame_id):\n        print('[No start ts found for %s]' % frame_id)\n        continue\n      current_frame_duration = trace['ts'] - frame_id_to_start_ts[frame_id]\n      total_frames += 1\n      completed_frame_id_and_duration_status.append(\n          (frame_id, current_frame_duration, args['termination_status']))\n      if(args['termination_status'] == 'missed_frame' or\n       args['termination_status'] == 'submitted_frame'):\n        drawn_frame_id_and_duration.append((frame_id, current_frame_duration))\n\n      # We are done with this frame_id so remove it from the dict.\n      frame_id_to_start_ts.pop(frame_id)\n      print('%d (%s with %s): %d' % (\n          total_frames, frame_id, args['termination_status'],\n          current_frame_duration))\n    elif args and (args.get('termination_status') in\n                   erroneous_termination_statuses):\n      # Invalidate previously collected results for this frame_id.\n      if frame_id_to_start_ts.get(frame_id):\n        print('[Invalidating %s due to %s]' % (\n            frame_id, args['termination_status']))\n        frame_id_to_start_ts.pop(frame_id)\n\n# Calculate metrics for total completed frames.\ntotal_completed_frames = len(completed_frame_id_and_duration_status)\nif total_completed_frames < 25:\n  raise Exception('Even with 3 loops found only %d frames' %\n                  total_completed_frames)\n# Get frame avg/min/max for the middle 25 frames.\nstart = (total_completed_frames - 25)/2\nprint('Got %d total completed frames. Using indexes [%d, %d).' % (\n    total_completed_frames, start, start+25))\nframe_max = 0\nframe_min = 0\nframe_cumulative = 0\naborted_frames = 0\nfor frame_id, duration, status in (\n    completed_frame_id_and_duration_status[start:start+25]):\n  frame_max = max(frame_max, duration)\n  frame_min = min(frame_min, duration) if frame_min else duration\n  frame_cumulative += duration\n  if status == 'main_frame_aborted':\n    aborted_frames += 1\n\nperf_results = {}\nperf_results['frame_max_us'] = frame_max\nperf_results['frame_min_us'] = frame_min\nperf_results['frame_avg_us'] = frame_cumulative/25\nperf_results['aborted_frames'] = aborted_frames\n\n# Now calculate metrics for only drawn frames.\ndrawn_frame_max = 0\ndrawn_frame_min = 0\ndrawn_frame_cumulative = 0\ntotal_drawn_frames = len(drawn_frame_id_and_duration)\nif total_drawn_frames < 25:\n  raise Exception('Even with 3 loops found only %d drawn frames' %\n                  total_drawn_frames)\n# Get drawn frame avg/min/max from the middle 25 frames.\nstart = (total_drawn_frames - 25)/2\nprint('Got %d total drawn frames. Using indexes [%d-%d).' % (\n      total_drawn_frames, start, start+25))\nfor frame_id, duration in drawn_frame_id_and_duration[start:start+25]:\n  drawn_frame_max = max(drawn_frame_max, duration)\n  drawn_frame_min = (min(drawn_frame_min, duration)\n                     if drawn_frame_min else duration)\n  drawn_frame_cumulative += duration\n# Add metrics to perf_results.\nperf_results['drawn_frame_max_us'] = drawn_frame_max\nperf_results['drawn_frame_min_us'] = drawn_frame_min\nperf_results['drawn_frame_avg_us'] = drawn_frame_cumulative/25\n\nprint('Final perf_results dict: %s' % perf_results)\n\n# Write perf_results to the output json.\nwith open(output_json_file, 'w') as f:\n  f.write(json.dumps(perf_results))\n",
62      "[CLEANUP]/g3_try_tmp_1/lottie1.json",
63      "/path/to/tmp/json",
64      "skottie-wasm"
65    ],
66    "env": {
67      "CHROME_HEADLESS": "1",
68      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
69    },
70    "name": "parse lottie1.json trace",
71    "~followup_annotations": [
72      "@@@STEP_LOG_LINE@json.output@{@@@",
73      "@@@STEP_LOG_LINE@json.output@  \"frame_avg_us\": 179.71, @@@",
74      "@@@STEP_LOG_LINE@json.output@  \"frame_max_us\": 218.25, @@@",
75      "@@@STEP_LOG_LINE@json.output@  \"frame_min_us\": 141.17@@@",
76      "@@@STEP_LOG_LINE@json.output@}@@@",
77      "@@@STEP_LOG_END@json.output@@@",
78      "@@@STEP_LOG_LINE@python.inline@@@@",
79      "@@@STEP_LOG_LINE@python.inline@import json@@@",
80      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
81      "@@@STEP_LOG_LINE@python.inline@@@@",
82      "@@@STEP_LOG_LINE@python.inline@trace_output = sys.argv[1]@@@",
83      "@@@STEP_LOG_LINE@python.inline@with open(trace_output, 'r') as f:@@@",
84      "@@@STEP_LOG_LINE@python.inline@  trace_json = json.load(f)@@@",
85      "@@@STEP_LOG_LINE@python.inline@output_json_file = sys.argv[2]@@@",
86      "@@@STEP_LOG_LINE@python.inline@renderer = sys.argv[3]  # Unused for now but might be useful in the future.@@@",
87      "@@@STEP_LOG_LINE@python.inline@@@@",
88      "@@@STEP_LOG_LINE@python.inline@# Output data about the GPU that was used.@@@",
89      "@@@STEP_LOG_LINE@python.inline@print('GPU data:')@@@",
90      "@@@STEP_LOG_LINE@python.inline@print(trace_json['metadata'].get('gpu-gl-renderer'))@@@",
91      "@@@STEP_LOG_LINE@python.inline@print(trace_json['metadata'].get('gpu-driver'))@@@",
92      "@@@STEP_LOG_LINE@python.inline@print(trace_json['metadata'].get('gpu-gl-vendor'))@@@",
93      "@@@STEP_LOG_LINE@python.inline@@@@",
94      "@@@STEP_LOG_LINE@python.inline@erroneous_termination_statuses = [@@@",
95      "@@@STEP_LOG_LINE@python.inline@    'replaced_by_new_reporter_at_same_stage',@@@",
96      "@@@STEP_LOG_LINE@python.inline@    'did_not_produce_frame',@@@",
97      "@@@STEP_LOG_LINE@python.inline@]@@@",
98      "@@@STEP_LOG_LINE@python.inline@accepted_termination_statuses = [@@@",
99      "@@@STEP_LOG_LINE@python.inline@    'missed_frame',@@@",
100      "@@@STEP_LOG_LINE@python.inline@    'submitted_frame',@@@",
101      "@@@STEP_LOG_LINE@python.inline@    'main_frame_aborted'@@@",
102      "@@@STEP_LOG_LINE@python.inline@]@@@",
103      "@@@STEP_LOG_LINE@python.inline@@@@",
104      "@@@STEP_LOG_LINE@python.inline@current_frame_duration = 0@@@",
105      "@@@STEP_LOG_LINE@python.inline@total_frames = 0@@@",
106      "@@@STEP_LOG_LINE@python.inline@frame_id_to_start_ts = {}@@@",
107      "@@@STEP_LOG_LINE@python.inline@# Will contain tuples of frame_ids and their duration and status.@@@",
108      "@@@STEP_LOG_LINE@python.inline@completed_frame_id_and_duration_status = []@@@",
109      "@@@STEP_LOG_LINE@python.inline@# Will contain tuples of drawn frame_ids and their duration.@@@",
110      "@@@STEP_LOG_LINE@python.inline@drawn_frame_id_and_duration = []@@@",
111      "@@@STEP_LOG_LINE@python.inline@for trace in trace_json['traceEvents']:@@@",
112      "@@@STEP_LOG_LINE@python.inline@  if 'PipelineReporter' in trace['name']:@@@",
113      "@@@STEP_LOG_LINE@python.inline@    frame_id = trace['id']@@@",
114      "@@@STEP_LOG_LINE@python.inline@    args = trace.get('args')@@@",
115      "@@@STEP_LOG_LINE@python.inline@    if args and args.get('step') == 'BeginImplFrameToSendBeginMainFrame':@@@",
116      "@@@STEP_LOG_LINE@python.inline@      frame_id_to_start_ts[frame_id] = trace['ts']@@@",
117      "@@@STEP_LOG_LINE@python.inline@    elif args and (args.get('termination_status') in@@@",
118      "@@@STEP_LOG_LINE@python.inline@                   accepted_termination_statuses):@@@",
119      "@@@STEP_LOG_LINE@python.inline@      if not frame_id_to_start_ts.get(frame_id):@@@",
120      "@@@STEP_LOG_LINE@python.inline@        print('[No start ts found for %s]' % frame_id)@@@",
121      "@@@STEP_LOG_LINE@python.inline@        continue@@@",
122      "@@@STEP_LOG_LINE@python.inline@      current_frame_duration = trace['ts'] - frame_id_to_start_ts[frame_id]@@@",
123      "@@@STEP_LOG_LINE@python.inline@      total_frames += 1@@@",
124      "@@@STEP_LOG_LINE@python.inline@      completed_frame_id_and_duration_status.append(@@@",
125      "@@@STEP_LOG_LINE@python.inline@          (frame_id, current_frame_duration, args['termination_status']))@@@",
126      "@@@STEP_LOG_LINE@python.inline@      if(args['termination_status'] == 'missed_frame' or@@@",
127      "@@@STEP_LOG_LINE@python.inline@       args['termination_status'] == 'submitted_frame'):@@@",
128      "@@@STEP_LOG_LINE@python.inline@        drawn_frame_id_and_duration.append((frame_id, current_frame_duration))@@@",
129      "@@@STEP_LOG_LINE@python.inline@@@@",
130      "@@@STEP_LOG_LINE@python.inline@      # We are done with this frame_id so remove it from the dict.@@@",
131      "@@@STEP_LOG_LINE@python.inline@      frame_id_to_start_ts.pop(frame_id)@@@",
132      "@@@STEP_LOG_LINE@python.inline@      print('%d (%s with %s): %d' % (@@@",
133      "@@@STEP_LOG_LINE@python.inline@          total_frames, frame_id, args['termination_status'],@@@",
134      "@@@STEP_LOG_LINE@python.inline@          current_frame_duration))@@@",
135      "@@@STEP_LOG_LINE@python.inline@    elif args and (args.get('termination_status') in@@@",
136      "@@@STEP_LOG_LINE@python.inline@                   erroneous_termination_statuses):@@@",
137      "@@@STEP_LOG_LINE@python.inline@      # Invalidate previously collected results for this frame_id.@@@",
138      "@@@STEP_LOG_LINE@python.inline@      if frame_id_to_start_ts.get(frame_id):@@@",
139      "@@@STEP_LOG_LINE@python.inline@        print('[Invalidating %s due to %s]' % (@@@",
140      "@@@STEP_LOG_LINE@python.inline@            frame_id, args['termination_status']))@@@",
141      "@@@STEP_LOG_LINE@python.inline@        frame_id_to_start_ts.pop(frame_id)@@@",
142      "@@@STEP_LOG_LINE@python.inline@@@@",
143      "@@@STEP_LOG_LINE@python.inline@# Calculate metrics for total completed frames.@@@",
144      "@@@STEP_LOG_LINE@python.inline@total_completed_frames = len(completed_frame_id_and_duration_status)@@@",
145      "@@@STEP_LOG_LINE@python.inline@if total_completed_frames < 25:@@@",
146      "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
147      "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
148      "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
149      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
150      "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
151      "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
152      "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
153      "@@@STEP_LOG_LINE@python.inline@frame_min = 0@@@",
154      "@@@STEP_LOG_LINE@python.inline@frame_cumulative = 0@@@",
155      "@@@STEP_LOG_LINE@python.inline@aborted_frames = 0@@@",
156      "@@@STEP_LOG_LINE@python.inline@for frame_id, duration, status in (@@@",
157      "@@@STEP_LOG_LINE@python.inline@    completed_frame_id_and_duration_status[start:start+25]):@@@",
158      "@@@STEP_LOG_LINE@python.inline@  frame_max = max(frame_max, duration)@@@",
159      "@@@STEP_LOG_LINE@python.inline@  frame_min = min(frame_min, duration) if frame_min else duration@@@",
160      "@@@STEP_LOG_LINE@python.inline@  frame_cumulative += duration@@@",
161      "@@@STEP_LOG_LINE@python.inline@  if status == 'main_frame_aborted':@@@",
162      "@@@STEP_LOG_LINE@python.inline@    aborted_frames += 1@@@",
163      "@@@STEP_LOG_LINE@python.inline@@@@",
164      "@@@STEP_LOG_LINE@python.inline@perf_results = {}@@@",
165      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_max_us'] = frame_max@@@",
166      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_min_us'] = frame_min@@@",
167      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_avg_us'] = frame_cumulative/25@@@",
168      "@@@STEP_LOG_LINE@python.inline@perf_results['aborted_frames'] = aborted_frames@@@",
169      "@@@STEP_LOG_LINE@python.inline@@@@",
170      "@@@STEP_LOG_LINE@python.inline@# Now calculate metrics for only drawn frames.@@@",
171      "@@@STEP_LOG_LINE@python.inline@drawn_frame_max = 0@@@",
172      "@@@STEP_LOG_LINE@python.inline@drawn_frame_min = 0@@@",
173      "@@@STEP_LOG_LINE@python.inline@drawn_frame_cumulative = 0@@@",
174      "@@@STEP_LOG_LINE@python.inline@total_drawn_frames = len(drawn_frame_id_and_duration)@@@",
175      "@@@STEP_LOG_LINE@python.inline@if total_drawn_frames < 25:@@@",
176      "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
177      "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
178      "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
179      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
180      "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
181      "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
182      "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
183      "@@@STEP_LOG_LINE@python.inline@  drawn_frame_max = max(drawn_frame_max, duration)@@@",
184      "@@@STEP_LOG_LINE@python.inline@  drawn_frame_min = (min(drawn_frame_min, duration)@@@",
185      "@@@STEP_LOG_LINE@python.inline@                     if drawn_frame_min else duration)@@@",
186      "@@@STEP_LOG_LINE@python.inline@  drawn_frame_cumulative += duration@@@",
187      "@@@STEP_LOG_LINE@python.inline@# Add metrics to perf_results.@@@",
188      "@@@STEP_LOG_LINE@python.inline@perf_results['drawn_frame_max_us'] = drawn_frame_max@@@",
189      "@@@STEP_LOG_LINE@python.inline@perf_results['drawn_frame_min_us'] = drawn_frame_min@@@",
190      "@@@STEP_LOG_LINE@python.inline@perf_results['drawn_frame_avg_us'] = drawn_frame_cumulative/25@@@",
191      "@@@STEP_LOG_LINE@python.inline@@@@",
192      "@@@STEP_LOG_LINE@python.inline@print('Final perf_results dict: %s' % perf_results)@@@",
193      "@@@STEP_LOG_LINE@python.inline@@@@",
194      "@@@STEP_LOG_LINE@python.inline@# Write perf_results to the output json.@@@",
195      "@@@STEP_LOG_LINE@python.inline@with open(output_json_file, 'w') as f:@@@",
196      "@@@STEP_LOG_LINE@python.inline@  f.write(json.dumps(perf_results))@@@",
197      "@@@STEP_LOG_END@python.inline@@@"
198    ]
199  },
200  {
201    "cmd": [
202      "[START_DIR]/node/node/bin/node",
203      "[START_DIR]/skia/tools/skottie-wasm-perf/skottie-wasm-perf.js",
204      "--canvaskit_js",
205      "[START_DIR]/build/canvaskit.js",
206      "--canvaskit_wasm",
207      "[START_DIR]/build/canvaskit.wasm",
208      "--input",
209      "[START_DIR]/lottie-samples/lottie2.json",
210      "--output",
211      "[CLEANUP]/g3_try_tmp_1/lottie2.json"
212    ],
213    "cwd": "[START_DIR]/skia/tools/skottie-wasm-perf",
214    "env": {
215      "CHROME_HEADLESS": "1",
216      "DISPLAY": ":0",
217      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
218    },
219    "infra_step": true,
220    "name": "Run perf cmd line app (2)"
221  },
222  {
223    "cmd": [
224      "python",
225      "-u",
226      "\nimport json\nimport sys\n\ntrace_output = sys.argv[1]\nwith open(trace_output, 'r') as f:\n  trace_json = json.load(f)\noutput_json_file = sys.argv[2]\nrenderer = sys.argv[3]  # Unused for now but might be useful in the future.\n\n# Output data about the GPU that was used.\nprint('GPU data:')\nprint(trace_json['metadata'].get('gpu-gl-renderer'))\nprint(trace_json['metadata'].get('gpu-driver'))\nprint(trace_json['metadata'].get('gpu-gl-vendor'))\n\nerroneous_termination_statuses = [\n    'replaced_by_new_reporter_at_same_stage',\n    'did_not_produce_frame',\n]\naccepted_termination_statuses = [\n    'missed_frame',\n    'submitted_frame',\n    'main_frame_aborted'\n]\n\ncurrent_frame_duration = 0\ntotal_frames = 0\nframe_id_to_start_ts = {}\n# Will contain tuples of frame_ids and their duration and status.\ncompleted_frame_id_and_duration_status = []\n# Will contain tuples of drawn frame_ids and their duration.\ndrawn_frame_id_and_duration = []\nfor trace in trace_json['traceEvents']:\n  if 'PipelineReporter' in trace['name']:\n    frame_id = trace['id']\n    args = trace.get('args')\n    if args and args.get('step') == 'BeginImplFrameToSendBeginMainFrame':\n      frame_id_to_start_ts[frame_id] = trace['ts']\n    elif args and (args.get('termination_status') in\n                   accepted_termination_statuses):\n      if not frame_id_to_start_ts.get(frame_id):\n        print('[No start ts found for %s]' % frame_id)\n        continue\n      current_frame_duration = trace['ts'] - frame_id_to_start_ts[frame_id]\n      total_frames += 1\n      completed_frame_id_and_duration_status.append(\n          (frame_id, current_frame_duration, args['termination_status']))\n      if(args['termination_status'] == 'missed_frame' or\n       args['termination_status'] == 'submitted_frame'):\n        drawn_frame_id_and_duration.append((frame_id, current_frame_duration))\n\n      # We are done with this frame_id so remove it from the dict.\n      frame_id_to_start_ts.pop(frame_id)\n      print('%d (%s with %s): %d' % (\n          total_frames, frame_id, args['termination_status'],\n          current_frame_duration))\n    elif args and (args.get('termination_status') in\n                   erroneous_termination_statuses):\n      # Invalidate previously collected results for this frame_id.\n      if frame_id_to_start_ts.get(frame_id):\n        print('[Invalidating %s due to %s]' % (\n            frame_id, args['termination_status']))\n        frame_id_to_start_ts.pop(frame_id)\n\n# Calculate metrics for total completed frames.\ntotal_completed_frames = len(completed_frame_id_and_duration_status)\nif total_completed_frames < 25:\n  raise Exception('Even with 3 loops found only %d frames' %\n                  total_completed_frames)\n# Get frame avg/min/max for the middle 25 frames.\nstart = (total_completed_frames - 25)/2\nprint('Got %d total completed frames. Using indexes [%d, %d).' % (\n    total_completed_frames, start, start+25))\nframe_max = 0\nframe_min = 0\nframe_cumulative = 0\naborted_frames = 0\nfor frame_id, duration, status in (\n    completed_frame_id_and_duration_status[start:start+25]):\n  frame_max = max(frame_max, duration)\n  frame_min = min(frame_min, duration) if frame_min else duration\n  frame_cumulative += duration\n  if status == 'main_frame_aborted':\n    aborted_frames += 1\n\nperf_results = {}\nperf_results['frame_max_us'] = frame_max\nperf_results['frame_min_us'] = frame_min\nperf_results['frame_avg_us'] = frame_cumulative/25\nperf_results['aborted_frames'] = aborted_frames\n\n# Now calculate metrics for only drawn frames.\ndrawn_frame_max = 0\ndrawn_frame_min = 0\ndrawn_frame_cumulative = 0\ntotal_drawn_frames = len(drawn_frame_id_and_duration)\nif total_drawn_frames < 25:\n  raise Exception('Even with 3 loops found only %d drawn frames' %\n                  total_drawn_frames)\n# Get drawn frame avg/min/max from the middle 25 frames.\nstart = (total_drawn_frames - 25)/2\nprint('Got %d total drawn frames. Using indexes [%d-%d).' % (\n      total_drawn_frames, start, start+25))\nfor frame_id, duration in drawn_frame_id_and_duration[start:start+25]:\n  drawn_frame_max = max(drawn_frame_max, duration)\n  drawn_frame_min = (min(drawn_frame_min, duration)\n                     if drawn_frame_min else duration)\n  drawn_frame_cumulative += duration\n# Add metrics to perf_results.\nperf_results['drawn_frame_max_us'] = drawn_frame_max\nperf_results['drawn_frame_min_us'] = drawn_frame_min\nperf_results['drawn_frame_avg_us'] = drawn_frame_cumulative/25\n\nprint('Final perf_results dict: %s' % perf_results)\n\n# Write perf_results to the output json.\nwith open(output_json_file, 'w') as f:\n  f.write(json.dumps(perf_results))\n",
227      "[CLEANUP]/g3_try_tmp_1/lottie2.json",
228      "/path/to/tmp/json",
229      "skottie-wasm"
230    ],
231    "env": {
232      "CHROME_HEADLESS": "1",
233      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
234    },
235    "name": "parse lottie2.json trace",
236    "~followup_annotations": [
237      "@@@STEP_LOG_LINE@json.output@{@@@",
238      "@@@STEP_LOG_LINE@json.output@  \"frame_avg_us\": 179.71, @@@",
239      "@@@STEP_LOG_LINE@json.output@  \"frame_max_us\": 218.25, @@@",
240      "@@@STEP_LOG_LINE@json.output@  \"frame_min_us\": 141.17@@@",
241      "@@@STEP_LOG_LINE@json.output@}@@@",
242      "@@@STEP_LOG_END@json.output@@@",
243      "@@@STEP_LOG_LINE@python.inline@@@@",
244      "@@@STEP_LOG_LINE@python.inline@import json@@@",
245      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
246      "@@@STEP_LOG_LINE@python.inline@@@@",
247      "@@@STEP_LOG_LINE@python.inline@trace_output = sys.argv[1]@@@",
248      "@@@STEP_LOG_LINE@python.inline@with open(trace_output, 'r') as f:@@@",
249      "@@@STEP_LOG_LINE@python.inline@  trace_json = json.load(f)@@@",
250      "@@@STEP_LOG_LINE@python.inline@output_json_file = sys.argv[2]@@@",
251      "@@@STEP_LOG_LINE@python.inline@renderer = sys.argv[3]  # Unused for now but might be useful in the future.@@@",
252      "@@@STEP_LOG_LINE@python.inline@@@@",
253      "@@@STEP_LOG_LINE@python.inline@# Output data about the GPU that was used.@@@",
254      "@@@STEP_LOG_LINE@python.inline@print('GPU data:')@@@",
255      "@@@STEP_LOG_LINE@python.inline@print(trace_json['metadata'].get('gpu-gl-renderer'))@@@",
256      "@@@STEP_LOG_LINE@python.inline@print(trace_json['metadata'].get('gpu-driver'))@@@",
257      "@@@STEP_LOG_LINE@python.inline@print(trace_json['metadata'].get('gpu-gl-vendor'))@@@",
258      "@@@STEP_LOG_LINE@python.inline@@@@",
259      "@@@STEP_LOG_LINE@python.inline@erroneous_termination_statuses = [@@@",
260      "@@@STEP_LOG_LINE@python.inline@    'replaced_by_new_reporter_at_same_stage',@@@",
261      "@@@STEP_LOG_LINE@python.inline@    'did_not_produce_frame',@@@",
262      "@@@STEP_LOG_LINE@python.inline@]@@@",
263      "@@@STEP_LOG_LINE@python.inline@accepted_termination_statuses = [@@@",
264      "@@@STEP_LOG_LINE@python.inline@    'missed_frame',@@@",
265      "@@@STEP_LOG_LINE@python.inline@    'submitted_frame',@@@",
266      "@@@STEP_LOG_LINE@python.inline@    'main_frame_aborted'@@@",
267      "@@@STEP_LOG_LINE@python.inline@]@@@",
268      "@@@STEP_LOG_LINE@python.inline@@@@",
269      "@@@STEP_LOG_LINE@python.inline@current_frame_duration = 0@@@",
270      "@@@STEP_LOG_LINE@python.inline@total_frames = 0@@@",
271      "@@@STEP_LOG_LINE@python.inline@frame_id_to_start_ts = {}@@@",
272      "@@@STEP_LOG_LINE@python.inline@# Will contain tuples of frame_ids and their duration and status.@@@",
273      "@@@STEP_LOG_LINE@python.inline@completed_frame_id_and_duration_status = []@@@",
274      "@@@STEP_LOG_LINE@python.inline@# Will contain tuples of drawn frame_ids and their duration.@@@",
275      "@@@STEP_LOG_LINE@python.inline@drawn_frame_id_and_duration = []@@@",
276      "@@@STEP_LOG_LINE@python.inline@for trace in trace_json['traceEvents']:@@@",
277      "@@@STEP_LOG_LINE@python.inline@  if 'PipelineReporter' in trace['name']:@@@",
278      "@@@STEP_LOG_LINE@python.inline@    frame_id = trace['id']@@@",
279      "@@@STEP_LOG_LINE@python.inline@    args = trace.get('args')@@@",
280      "@@@STEP_LOG_LINE@python.inline@    if args and args.get('step') == 'BeginImplFrameToSendBeginMainFrame':@@@",
281      "@@@STEP_LOG_LINE@python.inline@      frame_id_to_start_ts[frame_id] = trace['ts']@@@",
282      "@@@STEP_LOG_LINE@python.inline@    elif args and (args.get('termination_status') in@@@",
283      "@@@STEP_LOG_LINE@python.inline@                   accepted_termination_statuses):@@@",
284      "@@@STEP_LOG_LINE@python.inline@      if not frame_id_to_start_ts.get(frame_id):@@@",
285      "@@@STEP_LOG_LINE@python.inline@        print('[No start ts found for %s]' % frame_id)@@@",
286      "@@@STEP_LOG_LINE@python.inline@        continue@@@",
287      "@@@STEP_LOG_LINE@python.inline@      current_frame_duration = trace['ts'] - frame_id_to_start_ts[frame_id]@@@",
288      "@@@STEP_LOG_LINE@python.inline@      total_frames += 1@@@",
289      "@@@STEP_LOG_LINE@python.inline@      completed_frame_id_and_duration_status.append(@@@",
290      "@@@STEP_LOG_LINE@python.inline@          (frame_id, current_frame_duration, args['termination_status']))@@@",
291      "@@@STEP_LOG_LINE@python.inline@      if(args['termination_status'] == 'missed_frame' or@@@",
292      "@@@STEP_LOG_LINE@python.inline@       args['termination_status'] == 'submitted_frame'):@@@",
293      "@@@STEP_LOG_LINE@python.inline@        drawn_frame_id_and_duration.append((frame_id, current_frame_duration))@@@",
294      "@@@STEP_LOG_LINE@python.inline@@@@",
295      "@@@STEP_LOG_LINE@python.inline@      # We are done with this frame_id so remove it from the dict.@@@",
296      "@@@STEP_LOG_LINE@python.inline@      frame_id_to_start_ts.pop(frame_id)@@@",
297      "@@@STEP_LOG_LINE@python.inline@      print('%d (%s with %s): %d' % (@@@",
298      "@@@STEP_LOG_LINE@python.inline@          total_frames, frame_id, args['termination_status'],@@@",
299      "@@@STEP_LOG_LINE@python.inline@          current_frame_duration))@@@",
300      "@@@STEP_LOG_LINE@python.inline@    elif args and (args.get('termination_status') in@@@",
301      "@@@STEP_LOG_LINE@python.inline@                   erroneous_termination_statuses):@@@",
302      "@@@STEP_LOG_LINE@python.inline@      # Invalidate previously collected results for this frame_id.@@@",
303      "@@@STEP_LOG_LINE@python.inline@      if frame_id_to_start_ts.get(frame_id):@@@",
304      "@@@STEP_LOG_LINE@python.inline@        print('[Invalidating %s due to %s]' % (@@@",
305      "@@@STEP_LOG_LINE@python.inline@            frame_id, args['termination_status']))@@@",
306      "@@@STEP_LOG_LINE@python.inline@        frame_id_to_start_ts.pop(frame_id)@@@",
307      "@@@STEP_LOG_LINE@python.inline@@@@",
308      "@@@STEP_LOG_LINE@python.inline@# Calculate metrics for total completed frames.@@@",
309      "@@@STEP_LOG_LINE@python.inline@total_completed_frames = len(completed_frame_id_and_duration_status)@@@",
310      "@@@STEP_LOG_LINE@python.inline@if total_completed_frames < 25:@@@",
311      "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
312      "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
313      "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
314      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
315      "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
316      "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
317      "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
318      "@@@STEP_LOG_LINE@python.inline@frame_min = 0@@@",
319      "@@@STEP_LOG_LINE@python.inline@frame_cumulative = 0@@@",
320      "@@@STEP_LOG_LINE@python.inline@aborted_frames = 0@@@",
321      "@@@STEP_LOG_LINE@python.inline@for frame_id, duration, status in (@@@",
322      "@@@STEP_LOG_LINE@python.inline@    completed_frame_id_and_duration_status[start:start+25]):@@@",
323      "@@@STEP_LOG_LINE@python.inline@  frame_max = max(frame_max, duration)@@@",
324      "@@@STEP_LOG_LINE@python.inline@  frame_min = min(frame_min, duration) if frame_min else duration@@@",
325      "@@@STEP_LOG_LINE@python.inline@  frame_cumulative += duration@@@",
326      "@@@STEP_LOG_LINE@python.inline@  if status == 'main_frame_aborted':@@@",
327      "@@@STEP_LOG_LINE@python.inline@    aborted_frames += 1@@@",
328      "@@@STEP_LOG_LINE@python.inline@@@@",
329      "@@@STEP_LOG_LINE@python.inline@perf_results = {}@@@",
330      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_max_us'] = frame_max@@@",
331      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_min_us'] = frame_min@@@",
332      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_avg_us'] = frame_cumulative/25@@@",
333      "@@@STEP_LOG_LINE@python.inline@perf_results['aborted_frames'] = aborted_frames@@@",
334      "@@@STEP_LOG_LINE@python.inline@@@@",
335      "@@@STEP_LOG_LINE@python.inline@# Now calculate metrics for only drawn frames.@@@",
336      "@@@STEP_LOG_LINE@python.inline@drawn_frame_max = 0@@@",
337      "@@@STEP_LOG_LINE@python.inline@drawn_frame_min = 0@@@",
338      "@@@STEP_LOG_LINE@python.inline@drawn_frame_cumulative = 0@@@",
339      "@@@STEP_LOG_LINE@python.inline@total_drawn_frames = len(drawn_frame_id_and_duration)@@@",
340      "@@@STEP_LOG_LINE@python.inline@if total_drawn_frames < 25:@@@",
341      "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
342      "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
343      "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
344      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
345      "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
346      "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
347      "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
348      "@@@STEP_LOG_LINE@python.inline@  drawn_frame_max = max(drawn_frame_max, duration)@@@",
349      "@@@STEP_LOG_LINE@python.inline@  drawn_frame_min = (min(drawn_frame_min, duration)@@@",
350      "@@@STEP_LOG_LINE@python.inline@                     if drawn_frame_min else duration)@@@",
351      "@@@STEP_LOG_LINE@python.inline@  drawn_frame_cumulative += duration@@@",
352      "@@@STEP_LOG_LINE@python.inline@# Add metrics to perf_results.@@@",
353      "@@@STEP_LOG_LINE@python.inline@perf_results['drawn_frame_max_us'] = drawn_frame_max@@@",
354      "@@@STEP_LOG_LINE@python.inline@perf_results['drawn_frame_min_us'] = drawn_frame_min@@@",
355      "@@@STEP_LOG_LINE@python.inline@perf_results['drawn_frame_avg_us'] = drawn_frame_cumulative/25@@@",
356      "@@@STEP_LOG_LINE@python.inline@@@@",
357      "@@@STEP_LOG_LINE@python.inline@print('Final perf_results dict: %s' % perf_results)@@@",
358      "@@@STEP_LOG_LINE@python.inline@@@@",
359      "@@@STEP_LOG_LINE@python.inline@# Write perf_results to the output json.@@@",
360      "@@@STEP_LOG_LINE@python.inline@with open(output_json_file, 'w') as f:@@@",
361      "@@@STEP_LOG_LINE@python.inline@  f.write(json.dumps(perf_results))@@@",
362      "@@@STEP_LOG_END@python.inline@@@"
363    ]
364  },
365  {
366    "cmd": [
367      "[START_DIR]/node/node/bin/node",
368      "[START_DIR]/skia/tools/skottie-wasm-perf/skottie-wasm-perf.js",
369      "--canvaskit_js",
370      "[START_DIR]/build/canvaskit.js",
371      "--canvaskit_wasm",
372      "[START_DIR]/build/canvaskit.wasm",
373      "--input",
374      "[START_DIR]/lottie-samples/lottie3.json",
375      "--output",
376      "[CLEANUP]/g3_try_tmp_1/lottie3.json"
377    ],
378    "cwd": "[START_DIR]/skia/tools/skottie-wasm-perf",
379    "env": {
380      "CHROME_HEADLESS": "1",
381      "DISPLAY": ":0",
382      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
383    },
384    "infra_step": true,
385    "name": "Run perf cmd line app (3)"
386  },
387  {
388    "cmd": [
389      "python",
390      "-u",
391      "\nimport json\nimport sys\n\ntrace_output = sys.argv[1]\nwith open(trace_output, 'r') as f:\n  trace_json = json.load(f)\noutput_json_file = sys.argv[2]\nrenderer = sys.argv[3]  # Unused for now but might be useful in the future.\n\n# Output data about the GPU that was used.\nprint('GPU data:')\nprint(trace_json['metadata'].get('gpu-gl-renderer'))\nprint(trace_json['metadata'].get('gpu-driver'))\nprint(trace_json['metadata'].get('gpu-gl-vendor'))\n\nerroneous_termination_statuses = [\n    'replaced_by_new_reporter_at_same_stage',\n    'did_not_produce_frame',\n]\naccepted_termination_statuses = [\n    'missed_frame',\n    'submitted_frame',\n    'main_frame_aborted'\n]\n\ncurrent_frame_duration = 0\ntotal_frames = 0\nframe_id_to_start_ts = {}\n# Will contain tuples of frame_ids and their duration and status.\ncompleted_frame_id_and_duration_status = []\n# Will contain tuples of drawn frame_ids and their duration.\ndrawn_frame_id_and_duration = []\nfor trace in trace_json['traceEvents']:\n  if 'PipelineReporter' in trace['name']:\n    frame_id = trace['id']\n    args = trace.get('args')\n    if args and args.get('step') == 'BeginImplFrameToSendBeginMainFrame':\n      frame_id_to_start_ts[frame_id] = trace['ts']\n    elif args and (args.get('termination_status') in\n                   accepted_termination_statuses):\n      if not frame_id_to_start_ts.get(frame_id):\n        print('[No start ts found for %s]' % frame_id)\n        continue\n      current_frame_duration = trace['ts'] - frame_id_to_start_ts[frame_id]\n      total_frames += 1\n      completed_frame_id_and_duration_status.append(\n          (frame_id, current_frame_duration, args['termination_status']))\n      if(args['termination_status'] == 'missed_frame' or\n       args['termination_status'] == 'submitted_frame'):\n        drawn_frame_id_and_duration.append((frame_id, current_frame_duration))\n\n      # We are done with this frame_id so remove it from the dict.\n      frame_id_to_start_ts.pop(frame_id)\n      print('%d (%s with %s): %d' % (\n          total_frames, frame_id, args['termination_status'],\n          current_frame_duration))\n    elif args and (args.get('termination_status') in\n                   erroneous_termination_statuses):\n      # Invalidate previously collected results for this frame_id.\n      if frame_id_to_start_ts.get(frame_id):\n        print('[Invalidating %s due to %s]' % (\n            frame_id, args['termination_status']))\n        frame_id_to_start_ts.pop(frame_id)\n\n# Calculate metrics for total completed frames.\ntotal_completed_frames = len(completed_frame_id_and_duration_status)\nif total_completed_frames < 25:\n  raise Exception('Even with 3 loops found only %d frames' %\n                  total_completed_frames)\n# Get frame avg/min/max for the middle 25 frames.\nstart = (total_completed_frames - 25)/2\nprint('Got %d total completed frames. Using indexes [%d, %d).' % (\n    total_completed_frames, start, start+25))\nframe_max = 0\nframe_min = 0\nframe_cumulative = 0\naborted_frames = 0\nfor frame_id, duration, status in (\n    completed_frame_id_and_duration_status[start:start+25]):\n  frame_max = max(frame_max, duration)\n  frame_min = min(frame_min, duration) if frame_min else duration\n  frame_cumulative += duration\n  if status == 'main_frame_aborted':\n    aborted_frames += 1\n\nperf_results = {}\nperf_results['frame_max_us'] = frame_max\nperf_results['frame_min_us'] = frame_min\nperf_results['frame_avg_us'] = frame_cumulative/25\nperf_results['aborted_frames'] = aborted_frames\n\n# Now calculate metrics for only drawn frames.\ndrawn_frame_max = 0\ndrawn_frame_min = 0\ndrawn_frame_cumulative = 0\ntotal_drawn_frames = len(drawn_frame_id_and_duration)\nif total_drawn_frames < 25:\n  raise Exception('Even with 3 loops found only %d drawn frames' %\n                  total_drawn_frames)\n# Get drawn frame avg/min/max from the middle 25 frames.\nstart = (total_drawn_frames - 25)/2\nprint('Got %d total drawn frames. Using indexes [%d-%d).' % (\n      total_drawn_frames, start, start+25))\nfor frame_id, duration in drawn_frame_id_and_duration[start:start+25]:\n  drawn_frame_max = max(drawn_frame_max, duration)\n  drawn_frame_min = (min(drawn_frame_min, duration)\n                     if drawn_frame_min else duration)\n  drawn_frame_cumulative += duration\n# Add metrics to perf_results.\nperf_results['drawn_frame_max_us'] = drawn_frame_max\nperf_results['drawn_frame_min_us'] = drawn_frame_min\nperf_results['drawn_frame_avg_us'] = drawn_frame_cumulative/25\n\nprint('Final perf_results dict: %s' % perf_results)\n\n# Write perf_results to the output json.\nwith open(output_json_file, 'w') as f:\n  f.write(json.dumps(perf_results))\n",
392      "[CLEANUP]/g3_try_tmp_1/lottie3.json",
393      "/path/to/tmp/json",
394      "skottie-wasm"
395    ],
396    "env": {
397      "CHROME_HEADLESS": "1",
398      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
399    },
400    "name": "parse lottie3.json trace",
401    "~followup_annotations": [
402      "@@@STEP_LOG_LINE@json.output@{@@@",
403      "@@@STEP_LOG_LINE@json.output@  \"frame_avg_us\": 179.71, @@@",
404      "@@@STEP_LOG_LINE@json.output@  \"frame_max_us\": 218.25, @@@",
405      "@@@STEP_LOG_LINE@json.output@  \"frame_min_us\": 141.17@@@",
406      "@@@STEP_LOG_LINE@json.output@}@@@",
407      "@@@STEP_LOG_END@json.output@@@",
408      "@@@STEP_LOG_LINE@python.inline@@@@",
409      "@@@STEP_LOG_LINE@python.inline@import json@@@",
410      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
411      "@@@STEP_LOG_LINE@python.inline@@@@",
412      "@@@STEP_LOG_LINE@python.inline@trace_output = sys.argv[1]@@@",
413      "@@@STEP_LOG_LINE@python.inline@with open(trace_output, 'r') as f:@@@",
414      "@@@STEP_LOG_LINE@python.inline@  trace_json = json.load(f)@@@",
415      "@@@STEP_LOG_LINE@python.inline@output_json_file = sys.argv[2]@@@",
416      "@@@STEP_LOG_LINE@python.inline@renderer = sys.argv[3]  # Unused for now but might be useful in the future.@@@",
417      "@@@STEP_LOG_LINE@python.inline@@@@",
418      "@@@STEP_LOG_LINE@python.inline@# Output data about the GPU that was used.@@@",
419      "@@@STEP_LOG_LINE@python.inline@print('GPU data:')@@@",
420      "@@@STEP_LOG_LINE@python.inline@print(trace_json['metadata'].get('gpu-gl-renderer'))@@@",
421      "@@@STEP_LOG_LINE@python.inline@print(trace_json['metadata'].get('gpu-driver'))@@@",
422      "@@@STEP_LOG_LINE@python.inline@print(trace_json['metadata'].get('gpu-gl-vendor'))@@@",
423      "@@@STEP_LOG_LINE@python.inline@@@@",
424      "@@@STEP_LOG_LINE@python.inline@erroneous_termination_statuses = [@@@",
425      "@@@STEP_LOG_LINE@python.inline@    'replaced_by_new_reporter_at_same_stage',@@@",
426      "@@@STEP_LOG_LINE@python.inline@    'did_not_produce_frame',@@@",
427      "@@@STEP_LOG_LINE@python.inline@]@@@",
428      "@@@STEP_LOG_LINE@python.inline@accepted_termination_statuses = [@@@",
429      "@@@STEP_LOG_LINE@python.inline@    'missed_frame',@@@",
430      "@@@STEP_LOG_LINE@python.inline@    'submitted_frame',@@@",
431      "@@@STEP_LOG_LINE@python.inline@    'main_frame_aborted'@@@",
432      "@@@STEP_LOG_LINE@python.inline@]@@@",
433      "@@@STEP_LOG_LINE@python.inline@@@@",
434      "@@@STEP_LOG_LINE@python.inline@current_frame_duration = 0@@@",
435      "@@@STEP_LOG_LINE@python.inline@total_frames = 0@@@",
436      "@@@STEP_LOG_LINE@python.inline@frame_id_to_start_ts = {}@@@",
437      "@@@STEP_LOG_LINE@python.inline@# Will contain tuples of frame_ids and their duration and status.@@@",
438      "@@@STEP_LOG_LINE@python.inline@completed_frame_id_and_duration_status = []@@@",
439      "@@@STEP_LOG_LINE@python.inline@# Will contain tuples of drawn frame_ids and their duration.@@@",
440      "@@@STEP_LOG_LINE@python.inline@drawn_frame_id_and_duration = []@@@",
441      "@@@STEP_LOG_LINE@python.inline@for trace in trace_json['traceEvents']:@@@",
442      "@@@STEP_LOG_LINE@python.inline@  if 'PipelineReporter' in trace['name']:@@@",
443      "@@@STEP_LOG_LINE@python.inline@    frame_id = trace['id']@@@",
444      "@@@STEP_LOG_LINE@python.inline@    args = trace.get('args')@@@",
445      "@@@STEP_LOG_LINE@python.inline@    if args and args.get('step') == 'BeginImplFrameToSendBeginMainFrame':@@@",
446      "@@@STEP_LOG_LINE@python.inline@      frame_id_to_start_ts[frame_id] = trace['ts']@@@",
447      "@@@STEP_LOG_LINE@python.inline@    elif args and (args.get('termination_status') in@@@",
448      "@@@STEP_LOG_LINE@python.inline@                   accepted_termination_statuses):@@@",
449      "@@@STEP_LOG_LINE@python.inline@      if not frame_id_to_start_ts.get(frame_id):@@@",
450      "@@@STEP_LOG_LINE@python.inline@        print('[No start ts found for %s]' % frame_id)@@@",
451      "@@@STEP_LOG_LINE@python.inline@        continue@@@",
452      "@@@STEP_LOG_LINE@python.inline@      current_frame_duration = trace['ts'] - frame_id_to_start_ts[frame_id]@@@",
453      "@@@STEP_LOG_LINE@python.inline@      total_frames += 1@@@",
454      "@@@STEP_LOG_LINE@python.inline@      completed_frame_id_and_duration_status.append(@@@",
455      "@@@STEP_LOG_LINE@python.inline@          (frame_id, current_frame_duration, args['termination_status']))@@@",
456      "@@@STEP_LOG_LINE@python.inline@      if(args['termination_status'] == 'missed_frame' or@@@",
457      "@@@STEP_LOG_LINE@python.inline@       args['termination_status'] == 'submitted_frame'):@@@",
458      "@@@STEP_LOG_LINE@python.inline@        drawn_frame_id_and_duration.append((frame_id, current_frame_duration))@@@",
459      "@@@STEP_LOG_LINE@python.inline@@@@",
460      "@@@STEP_LOG_LINE@python.inline@      # We are done with this frame_id so remove it from the dict.@@@",
461      "@@@STEP_LOG_LINE@python.inline@      frame_id_to_start_ts.pop(frame_id)@@@",
462      "@@@STEP_LOG_LINE@python.inline@      print('%d (%s with %s): %d' % (@@@",
463      "@@@STEP_LOG_LINE@python.inline@          total_frames, frame_id, args['termination_status'],@@@",
464      "@@@STEP_LOG_LINE@python.inline@          current_frame_duration))@@@",
465      "@@@STEP_LOG_LINE@python.inline@    elif args and (args.get('termination_status') in@@@",
466      "@@@STEP_LOG_LINE@python.inline@                   erroneous_termination_statuses):@@@",
467      "@@@STEP_LOG_LINE@python.inline@      # Invalidate previously collected results for this frame_id.@@@",
468      "@@@STEP_LOG_LINE@python.inline@      if frame_id_to_start_ts.get(frame_id):@@@",
469      "@@@STEP_LOG_LINE@python.inline@        print('[Invalidating %s due to %s]' % (@@@",
470      "@@@STEP_LOG_LINE@python.inline@            frame_id, args['termination_status']))@@@",
471      "@@@STEP_LOG_LINE@python.inline@        frame_id_to_start_ts.pop(frame_id)@@@",
472      "@@@STEP_LOG_LINE@python.inline@@@@",
473      "@@@STEP_LOG_LINE@python.inline@# Calculate metrics for total completed frames.@@@",
474      "@@@STEP_LOG_LINE@python.inline@total_completed_frames = len(completed_frame_id_and_duration_status)@@@",
475      "@@@STEP_LOG_LINE@python.inline@if total_completed_frames < 25:@@@",
476      "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
477      "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
478      "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
479      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
480      "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
481      "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
482      "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
483      "@@@STEP_LOG_LINE@python.inline@frame_min = 0@@@",
484      "@@@STEP_LOG_LINE@python.inline@frame_cumulative = 0@@@",
485      "@@@STEP_LOG_LINE@python.inline@aborted_frames = 0@@@",
486      "@@@STEP_LOG_LINE@python.inline@for frame_id, duration, status in (@@@",
487      "@@@STEP_LOG_LINE@python.inline@    completed_frame_id_and_duration_status[start:start+25]):@@@",
488      "@@@STEP_LOG_LINE@python.inline@  frame_max = max(frame_max, duration)@@@",
489      "@@@STEP_LOG_LINE@python.inline@  frame_min = min(frame_min, duration) if frame_min else duration@@@",
490      "@@@STEP_LOG_LINE@python.inline@  frame_cumulative += duration@@@",
491      "@@@STEP_LOG_LINE@python.inline@  if status == 'main_frame_aborted':@@@",
492      "@@@STEP_LOG_LINE@python.inline@    aborted_frames += 1@@@",
493      "@@@STEP_LOG_LINE@python.inline@@@@",
494      "@@@STEP_LOG_LINE@python.inline@perf_results = {}@@@",
495      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_max_us'] = frame_max@@@",
496      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_min_us'] = frame_min@@@",
497      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_avg_us'] = frame_cumulative/25@@@",
498      "@@@STEP_LOG_LINE@python.inline@perf_results['aborted_frames'] = aborted_frames@@@",
499      "@@@STEP_LOG_LINE@python.inline@@@@",
500      "@@@STEP_LOG_LINE@python.inline@# Now calculate metrics for only drawn frames.@@@",
501      "@@@STEP_LOG_LINE@python.inline@drawn_frame_max = 0@@@",
502      "@@@STEP_LOG_LINE@python.inline@drawn_frame_min = 0@@@",
503      "@@@STEP_LOG_LINE@python.inline@drawn_frame_cumulative = 0@@@",
504      "@@@STEP_LOG_LINE@python.inline@total_drawn_frames = len(drawn_frame_id_and_duration)@@@",
505      "@@@STEP_LOG_LINE@python.inline@if total_drawn_frames < 25:@@@",
506      "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
507      "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
508      "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
509      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
510      "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
511      "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
512      "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
513      "@@@STEP_LOG_LINE@python.inline@  drawn_frame_max = max(drawn_frame_max, duration)@@@",
514      "@@@STEP_LOG_LINE@python.inline@  drawn_frame_min = (min(drawn_frame_min, duration)@@@",
515      "@@@STEP_LOG_LINE@python.inline@                     if drawn_frame_min else duration)@@@",
516      "@@@STEP_LOG_LINE@python.inline@  drawn_frame_cumulative += duration@@@",
517      "@@@STEP_LOG_LINE@python.inline@# Add metrics to perf_results.@@@",
518      "@@@STEP_LOG_LINE@python.inline@perf_results['drawn_frame_max_us'] = drawn_frame_max@@@",
519      "@@@STEP_LOG_LINE@python.inline@perf_results['drawn_frame_min_us'] = drawn_frame_min@@@",
520      "@@@STEP_LOG_LINE@python.inline@perf_results['drawn_frame_avg_us'] = drawn_frame_cumulative/25@@@",
521      "@@@STEP_LOG_LINE@python.inline@@@@",
522      "@@@STEP_LOG_LINE@python.inline@print('Final perf_results dict: %s' % perf_results)@@@",
523      "@@@STEP_LOG_LINE@python.inline@@@@",
524      "@@@STEP_LOG_LINE@python.inline@# Write perf_results to the output json.@@@",
525      "@@@STEP_LOG_LINE@python.inline@with open(output_json_file, 'w') as f:@@@",
526      "@@@STEP_LOG_LINE@python.inline@  f.write(json.dumps(perf_results))@@@",
527      "@@@STEP_LOG_END@python.inline@@@"
528    ]
529  },
530  {
531    "cmd": [
532      "python",
533      "-u",
534      "import os\nprint(os.environ.get('SWARMING_BOT_ID', ''))\n"
535    ],
536    "name": "get swarming bot id",
537    "~followup_annotations": [
538      "@@@STEP_LOG_LINE@python.inline@import os@@@",
539      "@@@STEP_LOG_LINE@python.inline@print(os.environ.get('SWARMING_BOT_ID', ''))@@@",
540      "@@@STEP_LOG_END@python.inline@@@"
541    ]
542  },
543  {
544    "cmd": [
545      "python",
546      "-u",
547      "import os\nprint(os.environ.get('SWARMING_TASK_ID', ''))\n"
548    ],
549    "name": "get swarming task id",
550    "~followup_annotations": [
551      "@@@STEP_LOG_LINE@python.inline@import os@@@",
552      "@@@STEP_LOG_LINE@python.inline@print(os.environ.get('SWARMING_TASK_ID', ''))@@@",
553      "@@@STEP_LOG_END@python.inline@@@"
554    ]
555  },
556  {
557    "cmd": [
558      "vpython",
559      "-u",
560      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
561      "--json-output",
562      "/path/to/tmp/json",
563      "ensure-directory",
564      "--mode",
565      "0777",
566      "[START_DIR]/[SWARM_OUT_DIR]"
567    ],
568    "infra_step": true,
569    "name": "makedirs perf_dir"
570  },
571  {
572    "cmd": [
573      "vpython",
574      "-u",
575      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
576      "--json-output",
577      "/path/to/tmp/json",
578      "copy",
579      "{\n    \"gitHash\": \"abc123\",\n    \"key\": {\n        \"arch\": \"wasm\",\n        \"bench_type\": \"tracing\",\n        \"compiler\": \"EMCC\",\n        \"configuration\": \"Release\",\n        \"cpu_or_gpu\": \"CPU\",\n        \"cpu_or_gpu_value\": \"AVX2\",\n        \"extra_config\": \"SkottieWASM\",\n        \"model\": \"GCE\",\n        \"os\": \"Debian10\",\n        \"source_type\": \"skottie\"\n    },\n    \"renderer\": \"skottie-wasm\",\n    \"results\": {\n        \"lottie1.json\": {\n            \"gl\": {\n                \"frame_avg_us\": 179.71,\n                \"frame_max_us\": 218.25,\n                \"frame_min_us\": 141.17\n            }\n        },\n        \"lottie2.json\": {\n            \"gl\": {\n                \"frame_avg_us\": 179.71,\n                \"frame_max_us\": 218.25,\n                \"frame_min_us\": 141.17\n            }\n        },\n        \"lottie3.json\": {\n            \"gl\": {\n                \"frame_avg_us\": 179.71,\n                \"frame_max_us\": 218.25,\n                \"frame_min_us\": 141.17\n            }\n        }\n    },\n    \"swarming_bot_id\": \"\",\n    \"swarming_task_id\": \"\"\n}",
580      "[START_DIR]/[SWARM_OUT_DIR]/perf_abc123_1337000001.json"
581    ],
582    "infra_step": true,
583    "name": "write output JSON",
584    "~followup_annotations": [
585      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@{@@@",
586      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    \"gitHash\": \"abc123\",@@@",
587      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    \"key\": {@@@",
588      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"arch\": \"wasm\",@@@",
589      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"bench_type\": \"tracing\",@@@",
590      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"compiler\": \"EMCC\",@@@",
591      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"configuration\": \"Release\",@@@",
592      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"cpu_or_gpu\": \"CPU\",@@@",
593      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"cpu_or_gpu_value\": \"AVX2\",@@@",
594      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"extra_config\": \"SkottieWASM\",@@@",
595      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"model\": \"GCE\",@@@",
596      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"os\": \"Debian10\",@@@",
597      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"source_type\": \"skottie\"@@@",
598      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    },@@@",
599      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    \"renderer\": \"skottie-wasm\",@@@",
600      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    \"results\": {@@@",
601      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"lottie1.json\": {@@@",
602      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@            \"gl\": {@@@",
603      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_avg_us\": 179.71,@@@",
604      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_max_us\": 218.25,@@@",
605      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_min_us\": 141.17@@@",
606      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@            }@@@",
607      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        },@@@",
608      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"lottie2.json\": {@@@",
609      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@            \"gl\": {@@@",
610      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_avg_us\": 179.71,@@@",
611      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_max_us\": 218.25,@@@",
612      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_min_us\": 141.17@@@",
613      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@            }@@@",
614      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        },@@@",
615      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        \"lottie3.json\": {@@@",
616      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@            \"gl\": {@@@",
617      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_avg_us\": 179.71,@@@",
618      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_max_us\": 218.25,@@@",
619      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@                \"frame_min_us\": 141.17@@@",
620      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@            }@@@",
621      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@        }@@@",
622      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    },@@@",
623      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    \"swarming_bot_id\": \"\",@@@",
624      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@    \"swarming_task_id\": \"\"@@@",
625      "@@@STEP_LOG_LINE@perf_abc123_1337000001.json@}@@@",
626      "@@@STEP_LOG_END@perf_abc123_1337000001.json@@@"
627    ]
628  },
629  {
630    "name": "$result"
631  }
632]