Add new SkottieTracing GPU bot to match SkottieWASM and LottieWeb

NoTry: true
Bug: skia:8884
Change-Id: I38e1fc050ef3ae101ccd75567f433ca6c3c0ddf3
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/222816
Reviewed-by: Joe Gregorio <jcgregorio@google.com>
Commit-Queue: Ravi Mistry <rmistry@google.com>
diff --git a/infra/bots/jobs.json b/infra/bots/jobs.json
index c0b9ca8..6a8df29 100644
--- a/infra/bots/jobs.json
+++ b/infra/bots/jobs.json
@@ -261,6 +261,7 @@
   "Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Debug-All",
   "Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Debug-All-Vulkan",
   "Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All",
+  "Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-SkottieTracing",
   "Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-Vulkan",
   "Perf-Debian9-Clang-NUCDE3815TYKHE-GPU-IntelBayTrail-x86_64-Debug-All",
   "Perf-Debian9-Clang-NUCDE3815TYKHE-GPU-IntelBayTrail-x86_64-Release-All",
diff --git a/infra/bots/recipes/perf_skottietrace.expected/Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-SkottieTracing.json b/infra/bots/recipes/perf_skottietrace.expected/Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-SkottieTracing.json
new file mode 100644
index 0000000..0d3e6c7
--- /dev/null
+++ b/infra/bots/recipes/perf_skottietrace.expected/Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-SkottieTracing.json
@@ -0,0 +1,572 @@
+[
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "ensure-directory",
+      "--mode",
+      "0777",
+      "[START_DIR]/tmp"
+    ],
+    "infra_step": true,
+    "name": "makedirs tmp_dir"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "copy",
+      "[START_DIR]/skia/infra/bots/assets/lottie-samples/VERSION",
+      "/path/to/tmp/"
+    ],
+    "infra_step": true,
+    "name": "Get lottie-samples VERSION"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "copy",
+      "42",
+      "[START_DIR]/tmp/LOTTIE_VERSION"
+    ],
+    "infra_step": true,
+    "name": "write LOTTIE_VERSION"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "rmtree",
+      "[START_DIR]/[SWARM_OUT_DIR]"
+    ],
+    "infra_step": true,
+    "name": "rmtree [SWARM_OUT_DIR]"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "ensure-directory",
+      "--mode",
+      "0777",
+      "[START_DIR]/[SWARM_OUT_DIR]"
+    ],
+    "infra_step": true,
+    "name": "makedirs [SWARM_OUT_DIR]"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "listdir",
+      "[START_DIR]/lottie-samples"
+    ],
+    "infra_step": true,
+    "name": "list lottie files",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@listdir@[START_DIR]/lottie-samples/LICENSE@@@",
+      "@@@STEP_LOG_LINE@listdir@[START_DIR]/lottie-samples/lottie 3!.json@@@",
+      "@@@STEP_LOG_LINE@listdir@[START_DIR]/lottie-samples/lottie(test)'!2.json@@@",
+      "@@@STEP_LOG_LINE@listdir@[START_DIR]/lottie-samples/lottie1.json@@@",
+      "@@@STEP_LOG_END@listdir@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[skia::flavor]/resources/symbolize_stack_trace.py",
+      "[START_DIR]",
+      "catchsegv",
+      "[START_DIR]/build/dm",
+      "--resourcePath",
+      "[START_DIR]/skia/resources",
+      "--lotties",
+      "[START_DIR]/lottie-samples",
+      "--src",
+      "lottie",
+      "--nonativeFonts",
+      "--verbose",
+      "--traceMatch",
+      "skottie",
+      "--trace",
+      "[START_DIR]/[SWARM_OUT_DIR]/2.json",
+      "--match",
+      "^lottie 3!.json$",
+      "--config",
+      "gles",
+      "--nocpu"
+    ],
+    "cwd": "[START_DIR]/skia",
+    "env": {
+      "CHROME_HEADLESS": "1",
+      "LD_LIBRARY_PATH": "[START_DIR]/mesa_intel_driver_linux",
+      "LIBGL_DRIVERS_PATH": "[START_DIR]/mesa_intel_driver_linux",
+      "PATH": "<PATH>:RECIPE_REPO[depot_tools]",
+      "VK_ICD_FILENAMES": "[START_DIR]/mesa_intel_driver_linux/intel_icd.x86_64.json"
+    },
+    "name": "symbolized dm"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "copy",
+      "[START_DIR]/[SWARM_OUT_DIR]/2.json",
+      "/path/to/tmp/"
+    ],
+    "infra_step": true,
+    "name": "read [START_DIR]/[SWARM_OUT_DIR]/2.json"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "\nimport json\nimport sys\n\ntrace_output = sys.argv[1]\ntrace_json = json.loads(trace_output)\nlottie_filename = sys.argv[2]\noutput_json_file = sys.argv[3]\n\nperf_results = {}\nframe_max = 0\nframe_min = 0\nframe_cumulative = 0\ncurrent_frame_duration = 0\ntotal_frames = 0\nframe_start = False\nskipped_first_seek = False  # Skip the first seek constructor call.\nfor trace in trace_json:\n  if 'skottie::Animation::seek' in trace['name']:\n    if not skipped_first_seek:\n      skipped_first_seek = True\n      continue\n    if frame_start:\n      raise Exception('We got consecutive Animation::seek without a ' +\n                      'render. Something is wrong.')\n    frame_start = True\n    current_frame_duration = trace['dur']\n  elif 'skottie::Animation::render' in trace['name']:\n    if not frame_start:\n      raise Exception('We got an Animation::render without a seek first. ' +\n                      'Something is wrong.')\n\n    current_frame_duration += trace['dur']\n    frame_start = False\n    total_frames += 1\n    frame_max = max(frame_max, current_frame_duration)\n    frame_min = (min(frame_min, current_frame_duration)\n                 if frame_min else current_frame_duration)\n    frame_cumulative += current_frame_duration\n\nexpected_dm_frames = 25\nif total_frames != expected_dm_frames:\n  raise Exception(\n      'Got ' + str(total_frames) + ' frames instead of ' +\n      str(expected_dm_frames))\nperf_results['frame_max_us'] = frame_max\nperf_results['frame_min_us'] = frame_min\nperf_results['frame_avg_us'] = frame_cumulative/total_frames\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",
+      "\n[{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":452,\"dur\":2.57,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void SkCanvas::drawPaint(const SkPaint &)\",\"ts\":473,\"dur\":2.67e+03,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":3.15e+03,\"dur\":2.25,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::render(SkCanvas *, const SkRect *, RenderFlags) const\",\"ts\":3.15e+03,\"dur\":216,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void SkCanvas::drawPath(const SkPath &, const SkPaint &)\",\"ts\":3.35e+03,\"dur\":15.1,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":3.37e+03,\"dur\":1.17,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::render(SkCanvas *, const SkRect *, RenderFlags) const\",\"ts\":3.37e+03,\"dur\":140,\"tid\":1,\"pid\":0}]\n",
+      "lottie 3!.json",
+      "/path/to/tmp/json"
+    ],
+    "env": {
+      "CHROME_HEADLESS": "1",
+      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
+    },
+    "name": "parse lottie 3!.json trace",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"frame_avg_us\": 179.71, @@@",
+      "@@@STEP_LOG_LINE@json.output@  \"frame_max_us\": 218.25, @@@",
+      "@@@STEP_LOG_LINE@json.output@  \"frame_min_us\": 141.17@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@import json@@@",
+      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@trace_output = sys.argv[1]@@@",
+      "@@@STEP_LOG_LINE@python.inline@trace_json = json.loads(trace_output)@@@",
+      "@@@STEP_LOG_LINE@python.inline@lottie_filename = sys.argv[2]@@@",
+      "@@@STEP_LOG_LINE@python.inline@output_json_file = sys.argv[3]@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@perf_results = {}@@@",
+      "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@frame_min = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@frame_cumulative = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@current_frame_duration = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@total_frames = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@frame_start = False@@@",
+      "@@@STEP_LOG_LINE@python.inline@skipped_first_seek = False  # Skip the first seek constructor call.@@@",
+      "@@@STEP_LOG_LINE@python.inline@for trace in trace_json:@@@",
+      "@@@STEP_LOG_LINE@python.inline@  if 'skottie::Animation::seek' in trace['name']:@@@",
+      "@@@STEP_LOG_LINE@python.inline@    if not skipped_first_seek:@@@",
+      "@@@STEP_LOG_LINE@python.inline@      skipped_first_seek = True@@@",
+      "@@@STEP_LOG_LINE@python.inline@      continue@@@",
+      "@@@STEP_LOG_LINE@python.inline@    if frame_start:@@@",
+      "@@@STEP_LOG_LINE@python.inline@      raise Exception('We got consecutive Animation::seek without a ' +@@@",
+      "@@@STEP_LOG_LINE@python.inline@                      'render. Something is wrong.')@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_start = True@@@",
+      "@@@STEP_LOG_LINE@python.inline@    current_frame_duration = trace['dur']@@@",
+      "@@@STEP_LOG_LINE@python.inline@  elif 'skottie::Animation::render' in trace['name']:@@@",
+      "@@@STEP_LOG_LINE@python.inline@    if not frame_start:@@@",
+      "@@@STEP_LOG_LINE@python.inline@      raise Exception('We got an Animation::render without a seek first. ' +@@@",
+      "@@@STEP_LOG_LINE@python.inline@                      'Something is wrong.')@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@    current_frame_duration += trace['dur']@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_start = False@@@",
+      "@@@STEP_LOG_LINE@python.inline@    total_frames += 1@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_max = max(frame_max, current_frame_duration)@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_min = (min(frame_min, current_frame_duration)@@@",
+      "@@@STEP_LOG_LINE@python.inline@                 if frame_min else current_frame_duration)@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_cumulative += current_frame_duration@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@expected_dm_frames = 25@@@",
+      "@@@STEP_LOG_LINE@python.inline@if total_frames != expected_dm_frames:@@@",
+      "@@@STEP_LOG_LINE@python.inline@  raise Exception(@@@",
+      "@@@STEP_LOG_LINE@python.inline@      'Got ' + str(total_frames) + ' frames instead of ' +@@@",
+      "@@@STEP_LOG_LINE@python.inline@      str(expected_dm_frames))@@@",
+      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_max_us'] = frame_max@@@",
+      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_min_us'] = frame_min@@@",
+      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_avg_us'] = frame_cumulative/total_frames@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@# Write perf_results to the output json.@@@",
+      "@@@STEP_LOG_LINE@python.inline@with open(output_json_file, 'w') as f:@@@",
+      "@@@STEP_LOG_LINE@python.inline@  f.write(json.dumps(perf_results))@@@",
+      "@@@STEP_LOG_END@python.inline@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "remove",
+      "[START_DIR]/[SWARM_OUT_DIR]/2.json"
+    ],
+    "infra_step": true,
+    "name": "remove [START_DIR]/[SWARM_OUT_DIR]/2.json"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[skia::flavor]/resources/symbolize_stack_trace.py",
+      "[START_DIR]",
+      "catchsegv",
+      "[START_DIR]/build/dm",
+      "--resourcePath",
+      "[START_DIR]/skia/resources",
+      "--lotties",
+      "[START_DIR]/lottie-samples",
+      "--src",
+      "lottie",
+      "--nonativeFonts",
+      "--verbose",
+      "--traceMatch",
+      "skottie",
+      "--trace",
+      "[START_DIR]/[SWARM_OUT_DIR]/3.json",
+      "--match",
+      "^lottie(test)'!2.json$",
+      "--config",
+      "gles",
+      "--nocpu"
+    ],
+    "cwd": "[START_DIR]/skia",
+    "env": {
+      "CHROME_HEADLESS": "1",
+      "LD_LIBRARY_PATH": "[START_DIR]/mesa_intel_driver_linux",
+      "LIBGL_DRIVERS_PATH": "[START_DIR]/mesa_intel_driver_linux",
+      "PATH": "<PATH>:RECIPE_REPO[depot_tools]",
+      "VK_ICD_FILENAMES": "[START_DIR]/mesa_intel_driver_linux/intel_icd.x86_64.json"
+    },
+    "name": "symbolized dm (2)"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "copy",
+      "[START_DIR]/[SWARM_OUT_DIR]/3.json",
+      "/path/to/tmp/"
+    ],
+    "infra_step": true,
+    "name": "read [START_DIR]/[SWARM_OUT_DIR]/3.json"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "\nimport json\nimport sys\n\ntrace_output = sys.argv[1]\ntrace_json = json.loads(trace_output)\nlottie_filename = sys.argv[2]\noutput_json_file = sys.argv[3]\n\nperf_results = {}\nframe_max = 0\nframe_min = 0\nframe_cumulative = 0\ncurrent_frame_duration = 0\ntotal_frames = 0\nframe_start = False\nskipped_first_seek = False  # Skip the first seek constructor call.\nfor trace in trace_json:\n  if 'skottie::Animation::seek' in trace['name']:\n    if not skipped_first_seek:\n      skipped_first_seek = True\n      continue\n    if frame_start:\n      raise Exception('We got consecutive Animation::seek without a ' +\n                      'render. Something is wrong.')\n    frame_start = True\n    current_frame_duration = trace['dur']\n  elif 'skottie::Animation::render' in trace['name']:\n    if not frame_start:\n      raise Exception('We got an Animation::render without a seek first. ' +\n                      'Something is wrong.')\n\n    current_frame_duration += trace['dur']\n    frame_start = False\n    total_frames += 1\n    frame_max = max(frame_max, current_frame_duration)\n    frame_min = (min(frame_min, current_frame_duration)\n                 if frame_min else current_frame_duration)\n    frame_cumulative += current_frame_duration\n\nexpected_dm_frames = 25\nif total_frames != expected_dm_frames:\n  raise Exception(\n      'Got ' + str(total_frames) + ' frames instead of ' +\n      str(expected_dm_frames))\nperf_results['frame_max_us'] = frame_max\nperf_results['frame_min_us'] = frame_min\nperf_results['frame_avg_us'] = frame_cumulative/total_frames\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",
+      "\n[{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":452,\"dur\":2.57,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void SkCanvas::drawPaint(const SkPaint &)\",\"ts\":473,\"dur\":2.67e+03,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":3.15e+03,\"dur\":2.25,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::render(SkCanvas *, const SkRect *, RenderFlags) const\",\"ts\":3.15e+03,\"dur\":216,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void SkCanvas::drawPath(const SkPath &, const SkPaint &)\",\"ts\":3.35e+03,\"dur\":15.1,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":3.37e+03,\"dur\":1.17,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::render(SkCanvas *, const SkRect *, RenderFlags) const\",\"ts\":3.37e+03,\"dur\":140,\"tid\":1,\"pid\":0}]\n",
+      "lottie(test)'!2.json",
+      "/path/to/tmp/json"
+    ],
+    "env": {
+      "CHROME_HEADLESS": "1",
+      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
+    },
+    "name": "parse lottie(test)'!2.json trace",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"frame_avg_us\": 179.71, @@@",
+      "@@@STEP_LOG_LINE@json.output@  \"frame_max_us\": 218.25, @@@",
+      "@@@STEP_LOG_LINE@json.output@  \"frame_min_us\": 141.17@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@import json@@@",
+      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@trace_output = sys.argv[1]@@@",
+      "@@@STEP_LOG_LINE@python.inline@trace_json = json.loads(trace_output)@@@",
+      "@@@STEP_LOG_LINE@python.inline@lottie_filename = sys.argv[2]@@@",
+      "@@@STEP_LOG_LINE@python.inline@output_json_file = sys.argv[3]@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@perf_results = {}@@@",
+      "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@frame_min = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@frame_cumulative = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@current_frame_duration = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@total_frames = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@frame_start = False@@@",
+      "@@@STEP_LOG_LINE@python.inline@skipped_first_seek = False  # Skip the first seek constructor call.@@@",
+      "@@@STEP_LOG_LINE@python.inline@for trace in trace_json:@@@",
+      "@@@STEP_LOG_LINE@python.inline@  if 'skottie::Animation::seek' in trace['name']:@@@",
+      "@@@STEP_LOG_LINE@python.inline@    if not skipped_first_seek:@@@",
+      "@@@STEP_LOG_LINE@python.inline@      skipped_first_seek = True@@@",
+      "@@@STEP_LOG_LINE@python.inline@      continue@@@",
+      "@@@STEP_LOG_LINE@python.inline@    if frame_start:@@@",
+      "@@@STEP_LOG_LINE@python.inline@      raise Exception('We got consecutive Animation::seek without a ' +@@@",
+      "@@@STEP_LOG_LINE@python.inline@                      'render. Something is wrong.')@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_start = True@@@",
+      "@@@STEP_LOG_LINE@python.inline@    current_frame_duration = trace['dur']@@@",
+      "@@@STEP_LOG_LINE@python.inline@  elif 'skottie::Animation::render' in trace['name']:@@@",
+      "@@@STEP_LOG_LINE@python.inline@    if not frame_start:@@@",
+      "@@@STEP_LOG_LINE@python.inline@      raise Exception('We got an Animation::render without a seek first. ' +@@@",
+      "@@@STEP_LOG_LINE@python.inline@                      'Something is wrong.')@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@    current_frame_duration += trace['dur']@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_start = False@@@",
+      "@@@STEP_LOG_LINE@python.inline@    total_frames += 1@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_max = max(frame_max, current_frame_duration)@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_min = (min(frame_min, current_frame_duration)@@@",
+      "@@@STEP_LOG_LINE@python.inline@                 if frame_min else current_frame_duration)@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_cumulative += current_frame_duration@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@expected_dm_frames = 25@@@",
+      "@@@STEP_LOG_LINE@python.inline@if total_frames != expected_dm_frames:@@@",
+      "@@@STEP_LOG_LINE@python.inline@  raise Exception(@@@",
+      "@@@STEP_LOG_LINE@python.inline@      'Got ' + str(total_frames) + ' frames instead of ' +@@@",
+      "@@@STEP_LOG_LINE@python.inline@      str(expected_dm_frames))@@@",
+      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_max_us'] = frame_max@@@",
+      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_min_us'] = frame_min@@@",
+      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_avg_us'] = frame_cumulative/total_frames@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@# Write perf_results to the output json.@@@",
+      "@@@STEP_LOG_LINE@python.inline@with open(output_json_file, 'w') as f:@@@",
+      "@@@STEP_LOG_LINE@python.inline@  f.write(json.dumps(perf_results))@@@",
+      "@@@STEP_LOG_END@python.inline@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "remove",
+      "[START_DIR]/[SWARM_OUT_DIR]/3.json"
+    ],
+    "infra_step": true,
+    "name": "remove [START_DIR]/[SWARM_OUT_DIR]/3.json"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[skia::flavor]/resources/symbolize_stack_trace.py",
+      "[START_DIR]",
+      "catchsegv",
+      "[START_DIR]/build/dm",
+      "--resourcePath",
+      "[START_DIR]/skia/resources",
+      "--lotties",
+      "[START_DIR]/lottie-samples",
+      "--src",
+      "lottie",
+      "--nonativeFonts",
+      "--verbose",
+      "--traceMatch",
+      "skottie",
+      "--trace",
+      "[START_DIR]/[SWARM_OUT_DIR]/4.json",
+      "--match",
+      "^lottie1.json$",
+      "--config",
+      "gles",
+      "--nocpu"
+    ],
+    "cwd": "[START_DIR]/skia",
+    "env": {
+      "CHROME_HEADLESS": "1",
+      "LD_LIBRARY_PATH": "[START_DIR]/mesa_intel_driver_linux",
+      "LIBGL_DRIVERS_PATH": "[START_DIR]/mesa_intel_driver_linux",
+      "PATH": "<PATH>:RECIPE_REPO[depot_tools]",
+      "VK_ICD_FILENAMES": "[START_DIR]/mesa_intel_driver_linux/intel_icd.x86_64.json"
+    },
+    "name": "symbolized dm (3)"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "copy",
+      "[START_DIR]/[SWARM_OUT_DIR]/4.json",
+      "/path/to/tmp/"
+    ],
+    "infra_step": true,
+    "name": "read [START_DIR]/[SWARM_OUT_DIR]/4.json"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "\nimport json\nimport sys\n\ntrace_output = sys.argv[1]\ntrace_json = json.loads(trace_output)\nlottie_filename = sys.argv[2]\noutput_json_file = sys.argv[3]\n\nperf_results = {}\nframe_max = 0\nframe_min = 0\nframe_cumulative = 0\ncurrent_frame_duration = 0\ntotal_frames = 0\nframe_start = False\nskipped_first_seek = False  # Skip the first seek constructor call.\nfor trace in trace_json:\n  if 'skottie::Animation::seek' in trace['name']:\n    if not skipped_first_seek:\n      skipped_first_seek = True\n      continue\n    if frame_start:\n      raise Exception('We got consecutive Animation::seek without a ' +\n                      'render. Something is wrong.')\n    frame_start = True\n    current_frame_duration = trace['dur']\n  elif 'skottie::Animation::render' in trace['name']:\n    if not frame_start:\n      raise Exception('We got an Animation::render without a seek first. ' +\n                      'Something is wrong.')\n\n    current_frame_duration += trace['dur']\n    frame_start = False\n    total_frames += 1\n    frame_max = max(frame_max, current_frame_duration)\n    frame_min = (min(frame_min, current_frame_duration)\n                 if frame_min else current_frame_duration)\n    frame_cumulative += current_frame_duration\n\nexpected_dm_frames = 25\nif total_frames != expected_dm_frames:\n  raise Exception(\n      'Got ' + str(total_frames) + ' frames instead of ' +\n      str(expected_dm_frames))\nperf_results['frame_max_us'] = frame_max\nperf_results['frame_min_us'] = frame_min\nperf_results['frame_avg_us'] = frame_cumulative/total_frames\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",
+      "\n[{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":452,\"dur\":2.57,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void SkCanvas::drawPaint(const SkPaint &)\",\"ts\":473,\"dur\":2.67e+03,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":3.15e+03,\"dur\":2.25,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::render(SkCanvas *, const SkRect *, RenderFlags) const\",\"ts\":3.15e+03,\"dur\":216,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void SkCanvas::drawPath(const SkPath &, const SkPaint &)\",\"ts\":3.35e+03,\"dur\":15.1,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::seek(SkScalar)\",\"ts\":3.37e+03,\"dur\":1.17,\"tid\":1,\"pid\":0},{\"ph\":\"X\",\"name\":\"void skottie::Animation::render(SkCanvas *, const SkRect *, RenderFlags) const\",\"ts\":3.37e+03,\"dur\":140,\"tid\":1,\"pid\":0}]\n",
+      "lottie1.json",
+      "/path/to/tmp/json"
+    ],
+    "env": {
+      "CHROME_HEADLESS": "1",
+      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
+    },
+    "name": "parse lottie1.json trace",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@json.output@{@@@",
+      "@@@STEP_LOG_LINE@json.output@  \"frame_avg_us\": 179.71, @@@",
+      "@@@STEP_LOG_LINE@json.output@  \"frame_max_us\": 218.25, @@@",
+      "@@@STEP_LOG_LINE@json.output@  \"frame_min_us\": 141.17@@@",
+      "@@@STEP_LOG_LINE@json.output@}@@@",
+      "@@@STEP_LOG_END@json.output@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@import json@@@",
+      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@trace_output = sys.argv[1]@@@",
+      "@@@STEP_LOG_LINE@python.inline@trace_json = json.loads(trace_output)@@@",
+      "@@@STEP_LOG_LINE@python.inline@lottie_filename = sys.argv[2]@@@",
+      "@@@STEP_LOG_LINE@python.inline@output_json_file = sys.argv[3]@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@perf_results = {}@@@",
+      "@@@STEP_LOG_LINE@python.inline@frame_max = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@frame_min = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@frame_cumulative = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@current_frame_duration = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@total_frames = 0@@@",
+      "@@@STEP_LOG_LINE@python.inline@frame_start = False@@@",
+      "@@@STEP_LOG_LINE@python.inline@skipped_first_seek = False  # Skip the first seek constructor call.@@@",
+      "@@@STEP_LOG_LINE@python.inline@for trace in trace_json:@@@",
+      "@@@STEP_LOG_LINE@python.inline@  if 'skottie::Animation::seek' in trace['name']:@@@",
+      "@@@STEP_LOG_LINE@python.inline@    if not skipped_first_seek:@@@",
+      "@@@STEP_LOG_LINE@python.inline@      skipped_first_seek = True@@@",
+      "@@@STEP_LOG_LINE@python.inline@      continue@@@",
+      "@@@STEP_LOG_LINE@python.inline@    if frame_start:@@@",
+      "@@@STEP_LOG_LINE@python.inline@      raise Exception('We got consecutive Animation::seek without a ' +@@@",
+      "@@@STEP_LOG_LINE@python.inline@                      'render. Something is wrong.')@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_start = True@@@",
+      "@@@STEP_LOG_LINE@python.inline@    current_frame_duration = trace['dur']@@@",
+      "@@@STEP_LOG_LINE@python.inline@  elif 'skottie::Animation::render' in trace['name']:@@@",
+      "@@@STEP_LOG_LINE@python.inline@    if not frame_start:@@@",
+      "@@@STEP_LOG_LINE@python.inline@      raise Exception('We got an Animation::render without a seek first. ' +@@@",
+      "@@@STEP_LOG_LINE@python.inline@                      'Something is wrong.')@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@    current_frame_duration += trace['dur']@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_start = False@@@",
+      "@@@STEP_LOG_LINE@python.inline@    total_frames += 1@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_max = max(frame_max, current_frame_duration)@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_min = (min(frame_min, current_frame_duration)@@@",
+      "@@@STEP_LOG_LINE@python.inline@                 if frame_min else current_frame_duration)@@@",
+      "@@@STEP_LOG_LINE@python.inline@    frame_cumulative += current_frame_duration@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@expected_dm_frames = 25@@@",
+      "@@@STEP_LOG_LINE@python.inline@if total_frames != expected_dm_frames:@@@",
+      "@@@STEP_LOG_LINE@python.inline@  raise Exception(@@@",
+      "@@@STEP_LOG_LINE@python.inline@      'Got ' + str(total_frames) + ' frames instead of ' +@@@",
+      "@@@STEP_LOG_LINE@python.inline@      str(expected_dm_frames))@@@",
+      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_max_us'] = frame_max@@@",
+      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_min_us'] = frame_min@@@",
+      "@@@STEP_LOG_LINE@python.inline@perf_results['frame_avg_us'] = frame_cumulative/total_frames@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@# Write perf_results to the output json.@@@",
+      "@@@STEP_LOG_LINE@python.inline@with open(output_json_file, 'w') as f:@@@",
+      "@@@STEP_LOG_LINE@python.inline@  f.write(json.dumps(perf_results))@@@",
+      "@@@STEP_LOG_END@python.inline@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "remove",
+      "[START_DIR]/[SWARM_OUT_DIR]/4.json"
+    ],
+    "infra_step": true,
+    "name": "remove [START_DIR]/[SWARM_OUT_DIR]/4.json"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "import os\nprint os.environ.get('SWARMING_BOT_ID', '')\n"
+    ],
+    "name": "get swarming bot id",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@python.inline@import os@@@",
+      "@@@STEP_LOG_LINE@python.inline@print os.environ.get('SWARMING_BOT_ID', '')@@@",
+      "@@@STEP_LOG_END@python.inline@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "import os\nprint os.environ.get('SWARMING_TASK_ID', '')\n"
+    ],
+    "name": "get swarming task id",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@python.inline@import os@@@",
+      "@@@STEP_LOG_LINE@python.inline@print os.environ.get('SWARMING_TASK_ID', '')@@@",
+      "@@@STEP_LOG_END@python.inline@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "ensure-directory",
+      "--mode",
+      "0777",
+      "[START_DIR]/[SWARM_OUT_DIR]"
+    ],
+    "infra_step": true,
+    "name": "makedirs perf_dir"
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "import json\nwith open('[START_DIR]/[SWARM_OUT_DIR]/perf_abc123_1337000001.json', 'w') as outfile:\n  json.dump(obj={'gitHash': 'abc123', 'results': {\"lottie(test)'!2.json\": {'gles': {'frame_avg_us': 179.71, 'frame_max_us': 218.25, 'frame_min_us': 141.17}}, 'lottie1.json': {'gles': {'frame_avg_us': 179.71, 'frame_max_us': 218.25, 'frame_min_us': 141.17}}, 'lottie 3!.json': {'gles': {'frame_avg_us': 179.71, 'frame_max_us': 218.25, 'frame_min_us': 141.17}}}, 'swarming_task_id': '', 'renderer': 'skottie', 'key': {'extra_config': 'SkottieTracing', 'bench_type': 'tracing', 'cpu_or_gpu_value': 'IntelIris640', 'arch': 'x86_64', 'source_type': 'skottie', 'cpu_or_gpu': 'GPU', 'model': 'NUC7i5BNK', 'configuration': 'Release', 'os': 'Debian9', 'compiler': 'Clang'}, 'swarming_bot_id': ''}, fp=outfile, indent=4)\n"
+    ],
+    "env": {
+      "CHROME_HEADLESS": "1",
+      "PATH": "<PATH>:RECIPE_REPO[depot_tools]"
+    },
+    "name": "write output JSON",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@python.inline@import json@@@",
+      "@@@STEP_LOG_LINE@python.inline@with open('[START_DIR]/[SWARM_OUT_DIR]/perf_abc123_1337000001.json', 'w') as outfile:@@@",
+      "@@@STEP_LOG_LINE@python.inline@  json.dump(obj={'gitHash': 'abc123', 'results': {\"lottie(test)'!2.json\": {'gles': {'frame_avg_us': 179.71, 'frame_max_us': 218.25, 'frame_min_us': 141.17}}, 'lottie1.json': {'gles': {'frame_avg_us': 179.71, 'frame_max_us': 218.25, 'frame_min_us': 141.17}}, 'lottie 3!.json': {'gles': {'frame_avg_us': 179.71, 'frame_max_us': 218.25, 'frame_min_us': 141.17}}}, 'swarming_task_id': '', 'renderer': 'skottie', 'key': {'extra_config': 'SkottieTracing', 'bench_type': 'tracing', 'cpu_or_gpu_value': 'IntelIris640', 'arch': 'x86_64', 'source_type': 'skottie', 'cpu_or_gpu': 'GPU', 'model': 'NUC7i5BNK', 'configuration': 'Release', 'os': 'Debian9', 'compiler': 'Clang'}, 'swarming_bot_id': ''}, fp=outfile, indent=4)@@@",
+      "@@@STEP_LOG_END@python.inline@@@"
+    ]
+  },
+  {
+    "name": "$result"
+  }
+]
\ No newline at end of file
diff --git a/infra/bots/recipes/perf_skottietrace.py b/infra/bots/recipes/perf_skottietrace.py
index 5fee886..f65abff 100644
--- a/infra/bots/recipes/perf_skottietrace.py
+++ b/infra/bots/recipes/perf_skottietrace.py
@@ -268,13 +268,32 @@
       'frame_min_us': 141.17,
       'frame_max_us': 218.25
   }
-  buildername = ('Perf-Android-Clang-AndroidOne-GPU-Mali400MP2-arm-Release-'
-                  'All-Android_SkottieTracing')
+  android_buildername = ('Perf-Android-Clang-AndroidOne-GPU-Mali400MP2-arm-'
+                         'Release-All-Android_SkottieTracing')
+  gpu_buildername = ('Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-'
+                     'Release-All-SkottieTracing')
   cpu_buildername = ('Perf-Debian9-Clang-GCE-CPU-AVX2-x86_64-Release-All-'
                      'SkottieTracing')
   yield (
-      api.test(buildername) +
-      api.properties(buildername=buildername,
+      api.test(android_buildername) +
+      api.properties(buildername=android_buildername,
+                     repository='https://skia.googlesource.com/skia.git',
+                     revision='abc123',
+                     task_id='abc123',
+                     trace_test_data=trace_output,
+                     dm_json_test_data=dm_json_test_data,
+                     path_config='kitchen',
+                     swarm_out_dir='[SWARM_OUT_DIR]') +
+      api.step_data('parse lottie(test)\'!2.json trace',
+                    api.json.output(parse_trace_json)) +
+      api.step_data('parse lottie1.json trace',
+                    api.json.output(parse_trace_json)) +
+      api.step_data('parse lottie 3!.json trace',
+                    api.json.output(parse_trace_json))
+  )
+  yield (
+      api.test(gpu_buildername) +
+      api.properties(buildername=gpu_buildername,
                      repository='https://skia.googlesource.com/skia.git',
                      revision='abc123',
                      task_id='abc123',
@@ -308,7 +327,7 @@
   )
   yield (
       api.test('skottietracing_parse_trace_error') +
-      api.properties(buildername=buildername,
+      api.properties(buildername=android_buildername,
                      repository='https://skia.googlesource.com/skia.git',
                      revision='abc123',
                      task_id='abc123',
@@ -321,7 +340,7 @@
   )
   yield (
       api.test('skottietracing_trybot') +
-      api.properties(buildername=buildername,
+      api.properties(buildername=android_buildername,
                      repository='https://skia.googlesource.com/skia.git',
                      revision='abc123',
                      task_id='abc123',
diff --git a/infra/bots/tasks.json b/infra/bots/tasks.json
index b54c0e4..49b5838 100755
--- a/infra/bots/tasks.json
+++ b/infra/bots/tasks.json
@@ -1322,6 +1322,11 @@
         "Upload-Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All"
       ]
     },
+    "Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-SkottieTracing": {
+      "tasks": [
+        "Upload-Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-SkottieTracing"
+      ]
+    },
     "Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-Vulkan": {
       "tasks": [
         "Upload-Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-Vulkan"
@@ -33986,6 +33991,127 @@
         "perf"
       ]
     },
+    "Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-SkottieTracing": {
+      "caches": [
+        {
+          "name": "vpython",
+          "path": "cache/vpython"
+        }
+      ],
+      "cipd_packages": [
+        {
+          "name": "infra/tools/luci/kitchen/${platform}",
+          "path": ".",
+          "version": "git_revision:d8f38ca9494b5af249942631f9cee45927f6b4bc"
+        },
+        {
+          "name": "infra/tools/luci-auth/${platform}",
+          "path": "cipd_bin_packages",
+          "version": "git_revision:2c805f1c716f6c5ad2126b27ec88b8585a09481e"
+        },
+        {
+          "name": "infra/tools/luci/vpython/${platform}",
+          "path": "cipd_bin_packages",
+          "version": "git_revision:96f81e737868d43124b4661cf1c325296ca04944"
+        },
+        {
+          "name": "skia/bots/skimage",
+          "path": "skimage",
+          "version": "version:39"
+        },
+        {
+          "name": "skia/bots/skp",
+          "path": "skp",
+          "version": "version:191"
+        },
+        {
+          "name": "skia/bots/svg",
+          "path": "svg",
+          "version": "version:9"
+        },
+        {
+          "name": "skia/bots/mesa_intel_driver_linux",
+          "path": "mesa_intel_driver_linux",
+          "version": "version:5"
+        },
+        {
+          "name": "skia/bots/lottie-samples",
+          "path": "lottie-samples",
+          "version": "version:1"
+        }
+      ],
+      "command": [
+        "./kitchen${EXECUTABLE_SUFFIX}",
+        "cook",
+        "-checkout-dir",
+        "recipe_bundle",
+        "-mode",
+        "swarming",
+        "-luci-system-account",
+        "system",
+        "-cache-dir",
+        "cache",
+        "-temp-dir",
+        "tmp",
+        "-known-gerrit-host",
+        "android.googlesource.com",
+        "-known-gerrit-host",
+        "boringssl.googlesource.com",
+        "-known-gerrit-host",
+        "chromium.googlesource.com",
+        "-known-gerrit-host",
+        "dart.googlesource.com",
+        "-known-gerrit-host",
+        "fuchsia.googlesource.com",
+        "-known-gerrit-host",
+        "go.googlesource.com",
+        "-known-gerrit-host",
+        "llvm.googlesource.com",
+        "-known-gerrit-host",
+        "skia.googlesource.com",
+        "-known-gerrit-host",
+        "webrtc.googlesource.com",
+        "-output-result-json",
+        "${ISOLATED_OUTDIR}/build_result_filename",
+        "-workdir",
+        ".",
+        "-recipe",
+        "perf_skottietrace",
+        "-properties",
+        "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildbucket_build_id\":\"<(BUILDBUCKET_BUILD_ID)\",\"buildername\":\"Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-SkottieTracing\",\"patch_issue\":\"<(ISSUE)\",\"patch_ref\":\"<(PATCH_REF)\",\"patch_repo\":\"<(PATCH_REPO)\",\"patch_set\":\"<(PATCHSET)\",\"patch_storage\":\"<(PATCH_STORAGE)\",\"repository\":\"<(REPO)\",\"revision\":\"<(REVISION)\",\"swarm_out_dir\":\"perf\",\"task_id\":\"<(TASK_ID)\"}",
+        "-logdog-annotation-url",
+        "logdog://logs.chromium.org/skia/<(TASK_ID)/+/annotations"
+      ],
+      "dependencies": [
+        "Housekeeper-PerCommit-BundleRecipes",
+        "Build-Debian9-Clang-x86_64-Release"
+      ],
+      "dimensions": [
+        "gpu:8086:5926",
+        "os:Debian-9.4",
+        "pool:Skia"
+      ],
+      "env_prefixes": {
+        "PATH": [
+          "cipd_bin_packages",
+          "cipd_bin_packages/bin"
+        ],
+        "VPYTHON_VIRTUALENV_ROOT": [
+          "cache/vpython"
+        ]
+      },
+      "execution_timeout_ns": 14400000000000,
+      "expiration_ns": 72000000000000,
+      "extra_tags": {
+        "log_location": "logdog://logs.chromium.org/skia/<(TASK_ID)/+/annotations"
+      },
+      "io_timeout_ns": 14400000000000,
+      "isolate": "perf_skia_bundled.isolate",
+      "max_attempts": 2,
+      "outputs": [
+        "perf"
+      ]
+    },
     "Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-Vulkan": {
       "caches": [
         {
@@ -88028,6 +88154,106 @@
       "max_attempts": 2,
       "service_account": "skia-external-nano-uploader@skia-swarming-bots.iam.gserviceaccount.com"
     },
+    "Upload-Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-SkottieTracing": {
+      "caches": [
+        {
+          "name": "vpython",
+          "path": "cache/vpython"
+        }
+      ],
+      "cipd_packages": [
+        {
+          "name": "infra/tools/luci/kitchen/${platform}",
+          "path": ".",
+          "version": "git_revision:d8f38ca9494b5af249942631f9cee45927f6b4bc"
+        },
+        {
+          "name": "infra/tools/luci-auth/${platform}",
+          "path": "cipd_bin_packages",
+          "version": "git_revision:2c805f1c716f6c5ad2126b27ec88b8585a09481e"
+        },
+        {
+          "name": "infra/tools/luci/vpython/${platform}",
+          "path": "cipd_bin_packages",
+          "version": "git_revision:96f81e737868d43124b4661cf1c325296ca04944"
+        },
+        {
+          "name": "infra/gsutil",
+          "path": "cipd_bin_packages",
+          "version": "version:4.28"
+        }
+      ],
+      "command": [
+        "./kitchen${EXECUTABLE_SUFFIX}",
+        "cook",
+        "-checkout-dir",
+        "recipe_bundle",
+        "-mode",
+        "swarming",
+        "-luci-system-account",
+        "system",
+        "-cache-dir",
+        "cache",
+        "-temp-dir",
+        "tmp",
+        "-known-gerrit-host",
+        "android.googlesource.com",
+        "-known-gerrit-host",
+        "boringssl.googlesource.com",
+        "-known-gerrit-host",
+        "chromium.googlesource.com",
+        "-known-gerrit-host",
+        "dart.googlesource.com",
+        "-known-gerrit-host",
+        "fuchsia.googlesource.com",
+        "-known-gerrit-host",
+        "go.googlesource.com",
+        "-known-gerrit-host",
+        "llvm.googlesource.com",
+        "-known-gerrit-host",
+        "skia.googlesource.com",
+        "-known-gerrit-host",
+        "webrtc.googlesource.com",
+        "-output-result-json",
+        "${ISOLATED_OUTDIR}/build_result_filename",
+        "-workdir",
+        ".",
+        "-recipe",
+        "upload_nano_results",
+        "-properties",
+        "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildbucket_build_id\":\"<(BUILDBUCKET_BUILD_ID)\",\"buildername\":\"Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-SkottieTracing\",\"gs_bucket\":\"skia-perf\",\"patch_issue\":\"<(ISSUE)\",\"patch_ref\":\"<(PATCH_REF)\",\"patch_repo\":\"<(PATCH_REPO)\",\"patch_set\":\"<(PATCHSET)\",\"patch_storage\":\"<(PATCH_STORAGE)\",\"repository\":\"<(REPO)\",\"revision\":\"<(REVISION)\",\"swarm_out_dir\":\"output_ignored\",\"task_id\":\"<(TASK_ID)\"}",
+        "-logdog-annotation-url",
+        "logdog://logs.chromium.org/skia/<(TASK_ID)/+/annotations"
+      ],
+      "dependencies": [
+        "Housekeeper-PerCommit-BundleRecipes",
+        "Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-SkottieTracing"
+      ],
+      "dimensions": [
+        "cpu:x86-64-Haswell_GCE",
+        "gpu:none",
+        "machine_type:n1-highmem-2",
+        "os:Debian-9.8",
+        "pool:Skia"
+      ],
+      "env_prefixes": {
+        "PATH": [
+          "cipd_bin_packages",
+          "cipd_bin_packages/bin"
+        ],
+        "VPYTHON_VIRTUALENV_ROOT": [
+          "cache/vpython"
+        ]
+      },
+      "execution_timeout_ns": 3600000000000,
+      "extra_tags": {
+        "log_location": "logdog://logs.chromium.org/skia/<(TASK_ID)/+/annotations"
+      },
+      "io_timeout_ns": 3600000000000,
+      "isolate": "swarm_recipe.isolate",
+      "max_attempts": 2,
+      "service_account": "skia-external-nano-uploader@skia-swarming-bots.iam.gserviceaccount.com"
+    },
     "Upload-Perf-Debian9-Clang-NUC7i5BNK-GPU-IntelIris640-x86_64-Release-All-Vulkan": {
       "caches": [
         {