[infra] Fix dangling Python2-specific issues

subprocess.check_output needs encoding or it defaults
to bytes.

Python 3 has / be float division and // be integer
division.

The skpbench fix is speculative.

Change-Id: I13d0e976c03bba30761c8ab533e6fdd041b795c8
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/541696
Reviewed-by: Ravi Mistry <rmistry@google.com>
diff --git a/infra/bots/buildstats/buildstats_flutter.py b/infra/bots/buildstats/buildstats_flutter.py
index d283fe9..c39cf04 100644
--- a/infra/bots/buildstats/buildstats_flutter.py
+++ b/infra/bots/buildstats/buildstats_flutter.py
@@ -6,7 +6,6 @@
 """Writes a Perf-formated json file with stats about Skia's size in flutter."""
 
 
-from __future__ import print_function
 import json
 import os
 import subprocess
@@ -46,32 +45,36 @@
   print(magic_seperator)
   print('Report by file, then by symbol with ellided/combined templates')
   lines = subprocess.check_output([bloaty_path, stripped_file,
-                                 '-d', 'compileunits,symbols', '-s', 'file',
-                                 '-n', '0', '--tsv', '--demangle=short',
-                                 '--debug-file=%s' % symbols_file])
+                                   '-d', 'compileunits,symbols', '-s', 'file',
+                                   '-n', '0', '--tsv', '--demangle=short',
+                                   '--debug-file=%s' % symbols_file],
+                                  encoding='utf-8')
   grand_total = print_skia_lines_file_symbol(lines)
   print(magic_seperator)
   print('Report by file, then by symbol with full templates')
   lines = subprocess.check_output([bloaty_path, stripped_file,
-                                 '-d', 'compileunits,symbols', '-s', 'file',
-                                 '-n', '0', '--tsv', '--demangle=full',
-                                 '--debug-file=%s' % symbols_file])
+                                   '-d', 'compileunits,symbols', '-s', 'file',
+                                   '-n', '0', '--tsv', '--demangle=full',
+                                   '--debug-file=%s' % symbols_file],
+                                  encoding='utf-8')
   print_skia_lines_file_symbol(lines)
   print(magic_seperator)
 
   print('Report by symbol, then by file with ellided/combined templates')
   lines = subprocess.check_output([bloaty_path, stripped_file,
-                                 '-d', 'symbols,compileunits', '-s', 'file',
-                                 '-n', '0', '--tsv', '--demangle=short',
-                                 '--debug-file=%s' % symbols_file])
+                                   '-d', 'symbols,compileunits', '-s', 'file',
+                                   '-n', '0', '--tsv', '--demangle=short',
+                                   '--debug-file=%s' % symbols_file],
+                                  encoding='utf-8')
   print_skia_lines_symbol_file(lines)
   print(magic_seperator)
 
   print('Report by symbol, then by file with full templates')
   lines = subprocess.check_output([bloaty_path, stripped_file,
-                                 '-d', 'symbols,compileunits', '-s', 'file',
-                                 '-n', '0', '--tsv', '--demangle=full',
-                                 '--debug-file=%s' % symbols_file])
+                                   '-d', 'symbols,compileunits', '-s', 'file',
+                                   '-n', '0', '--tsv', '--demangle=full',
+                                   '--debug-file=%s' % symbols_file],
+                                  encoding='utf-8')
   print_skia_lines_symbol_file(lines)
   print(magic_seperator)
 
diff --git a/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_canvas_perf.json b/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_canvas_perf.json
index f757e2d..4d6baf0 100644
--- a/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_canvas_perf.json
+++ b/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_canvas_perf.json
@@ -56,7 +56,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie1.json",
       "/path/to/tmp/json",
       "lottie-web"
@@ -144,7 +144,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -174,7 +174,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
@@ -219,7 +219,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie2.json",
       "/path/to/tmp/json",
       "lottie-web"
@@ -307,7 +307,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -337,7 +337,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
@@ -382,7 +382,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie3.json",
       "/path/to/tmp/json",
       "lottie-web"
@@ -470,7 +470,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -500,7 +500,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
diff --git a/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_canvas_perf_trybot.json b/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_canvas_perf_trybot.json
index 57632c2..7aa94a3 100644
--- a/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_canvas_perf_trybot.json
+++ b/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_canvas_perf_trybot.json
@@ -56,7 +56,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie1.json",
       "/path/to/tmp/json",
       "lottie-web"
@@ -144,7 +144,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -174,7 +174,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
@@ -219,7 +219,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie2.json",
       "/path/to/tmp/json",
       "lottie-web"
@@ -307,7 +307,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -337,7 +337,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
@@ -382,7 +382,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie3.json",
       "/path/to/tmp/json",
       "lottie-web"
@@ -470,7 +470,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -500,7 +500,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
diff --git a/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_perf.json b/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_perf.json
index 545017a..54e40c4 100644
--- a/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_perf.json
+++ b/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_perf.json
@@ -56,7 +56,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie1.json",
       "/path/to/tmp/json",
       "lottie-web"
@@ -144,7 +144,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -174,7 +174,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
@@ -219,7 +219,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie2.json",
       "/path/to/tmp/json",
       "lottie-web"
@@ -307,7 +307,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -337,7 +337,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
@@ -382,7 +382,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie3.json",
       "/path/to/tmp/json",
       "lottie-web"
@@ -470,7 +470,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -500,7 +500,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
diff --git a/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_perf_trybot.json b/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_perf_trybot.json
index 8e8dafd..db05ac0 100644
--- a/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_perf_trybot.json
+++ b/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/lottie_web_perf_trybot.json
@@ -56,7 +56,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie1.json",
       "/path/to/tmp/json",
       "lottie-web"
@@ -144,7 +144,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -174,7 +174,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
@@ -219,7 +219,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie2.json",
       "/path/to/tmp/json",
       "lottie-web"
@@ -307,7 +307,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -337,7 +337,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
@@ -382,7 +382,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie3.json",
       "/path/to/tmp/json",
       "lottie-web"
@@ -470,7 +470,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -500,7 +500,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
diff --git a/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/skottie_wasm_perf.json b/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/skottie_wasm_perf.json
index c0aa12b..62877e0 100644
--- a/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/skottie_wasm_perf.json
+++ b/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/skottie_wasm_perf.json
@@ -58,7 +58,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie1.json",
       "/path/to/tmp/json",
       "skottie-wasm"
@@ -146,7 +146,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -176,7 +176,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
@@ -223,7 +223,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie2.json",
       "/path/to/tmp/json",
       "skottie-wasm"
@@ -311,7 +311,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -341,7 +341,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
@@ -388,7 +388,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie3.json",
       "/path/to/tmp/json",
       "skottie-wasm"
@@ -476,7 +476,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -506,7 +506,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
diff --git a/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/skottie_wasm_perf_gpu.json b/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/skottie_wasm_perf_gpu.json
index a88f8cc..e86ce64 100644
--- a/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/skottie_wasm_perf_gpu.json
+++ b/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/skottie_wasm_perf_gpu.json
@@ -59,7 +59,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie1.json",
       "/path/to/tmp/json",
       "skottie-wasm"
@@ -147,7 +147,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -177,7 +177,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
@@ -225,7 +225,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie2.json",
       "/path/to/tmp/json",
       "skottie-wasm"
@@ -313,7 +313,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -343,7 +343,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
@@ -391,7 +391,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie3.json",
       "/path/to/tmp/json",
       "skottie-wasm"
@@ -479,7 +479,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -509,7 +509,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
diff --git a/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/skottie_wasm_perf_trybot.json b/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/skottie_wasm_perf_trybot.json
index 17ebda2..b9260f5 100644
--- a/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/skottie_wasm_perf_trybot.json
+++ b/infra/bots/recipes/perf_skottiewasm_lottieweb.expected/skottie_wasm_perf_trybot.json
@@ -58,7 +58,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie1.json",
       "/path/to/tmp/json",
       "skottie-wasm"
@@ -146,7 +146,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -176,7 +176,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
@@ -223,7 +223,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie2.json",
       "/path/to/tmp/json",
       "skottie-wasm"
@@ -311,7 +311,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -341,7 +341,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
@@ -388,7 +388,7 @@
     "cmd": [
       "python",
       "-u",
-      "\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",
+      "\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",
       "[CLEANUP]/g3_try_tmp_1/lottie3.json",
       "/path/to/tmp/json",
       "skottie-wasm"
@@ -476,7 +476,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_completed_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get frame avg/min/max for the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_completed_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total completed frames. Using indexes [%d, %d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@    total_completed_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
@@ -506,7 +506,7 @@
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('Even with 3 loops found only %d drawn frames' %@@@",
       "@@@STEP_LOG_LINE@python.inline@                  total_drawn_frames)@@@",
       "@@@STEP_LOG_LINE@python.inline@# Get drawn frame avg/min/max from the middle 25 frames.@@@",
-      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25)/2@@@",
+      "@@@STEP_LOG_LINE@python.inline@start = (total_drawn_frames - 25) // 2@@@",
       "@@@STEP_LOG_LINE@python.inline@print('Got %d total drawn frames. Using indexes [%d-%d).' % (@@@",
       "@@@STEP_LOG_LINE@python.inline@      total_drawn_frames, start, start+25))@@@",
       "@@@STEP_LOG_LINE@python.inline@for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:@@@",
diff --git a/infra/bots/recipes/perf_skottiewasm_lottieweb.py b/infra/bots/recipes/perf_skottiewasm_lottieweb.py
index 275a862..ab8adc3 100644
--- a/infra/bots/recipes/perf_skottiewasm_lottieweb.py
+++ b/infra/bots/recipes/perf_skottiewasm_lottieweb.py
@@ -287,7 +287,7 @@
     raise Exception('Even with 3 loops found only %d frames' %
                     total_completed_frames)
   # Get frame avg/min/max for the middle 25 frames.
-  start = (total_completed_frames - 25)/2
+  start = (total_completed_frames - 25) // 2
   print('Got %d total completed frames. Using indexes [%d, %d).' % (
       total_completed_frames, start, start+25))
   frame_max = 0
@@ -317,7 +317,7 @@
     raise Exception('Even with 3 loops found only %d drawn frames' %
                     total_drawn_frames)
   # Get drawn frame avg/min/max from the middle 25 frames.
-  start = (total_drawn_frames - 25)/2
+  start = (total_drawn_frames - 25) // 2
   print('Got %d total drawn frames. Using indexes [%d-%d).' % (
         total_drawn_frames, start, start+25))
   for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:
diff --git a/tools/skpbench/_adb.py b/tools/skpbench/_adb.py
index 9601dcb..ebaf1d1 100644
--- a/tools/skpbench/_adb.py
+++ b/tools/skpbench/_adb.py
@@ -27,7 +27,7 @@
     if self.__echo:
       self.__echo_shell_cmd(cmd)
     self.__establish_connection()
-    result = subprocess.check_output(self.__invocation + ['shell', cmd])
+    result = subprocess.check_output(self.__invocation + ['shell', cmd], encoding='utf-8')
     if self.__echo:
       print(result, file=sys.stderr)
     return result
diff --git a/tools/skpbench/skpbench.py b/tools/skpbench/skpbench.py
index 68e4b06..18219ea 100755
--- a/tools/skpbench/skpbench.py
+++ b/tools/skpbench/skpbench.py
@@ -183,7 +183,7 @@
   def get_header(cls, outfile=sys.stdout):
     commandline = cls.ARGV + ['--duration', '0']
     dump_commandline_if_verbose(commandline)
-    out = subprocess.check_output(commandline, stderr=subprocess.STDOUT)
+    out = subprocess.check_output(commandline, stderr=subprocess.STDOUT, encoding='utf-8')
     return out.rstrip()
 
   @classmethod
@@ -195,10 +195,10 @@
                               '--config', config,
                               '--src', 'warmup']
     dump_commandline_if_verbose(commandline)
-    output = subprocess.check_output(commandline, stderr=subprocess.STDOUT)
+    output = subprocess.check_output(commandline, stderr=subprocess.STDOUT, encoding='utf-8')
 
     # validate the warmup run output.
-    for line in output.decode('utf-8').split('\n'):
+    for line in output.split('\n'):
       match = BenchResult.match(line.rstrip())
       if match and match.bench == 'warmup':
         return