Track Skia's Code size in Flutter

This creates a nice readable display, since Bloaty
doesn't allow filtering through the CLI.

Additionally, rename the flutter job to accurately
represent what settings it actually is (32 bit ARM built
with clang).

Bug: skia:
Change-Id: Iaed313caf43a31105adc8c85c545cc6cb2bcbe30
Reviewed-on: https://skia-review.googlesource.com/c/160920
Reviewed-by: Mike Klein <mtklein@google.com>
Reviewed-by: Eric Boren <borenet@google.com>
Commit-Queue: Kevin Lubick <kjlubick@google.com>
diff --git a/infra/bots/buildstats/buildstats_flutter.py b/infra/bots/buildstats/buildstats_flutter.py
new file mode 100644
index 0000000..764c71b
--- /dev/null
+++ b/infra/bots/buildstats/buildstats_flutter.py
@@ -0,0 +1,151 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+"""Writes a Perf-formated json file with stats about Skia's size in flutter."""
+
+
+import json
+import os
+import subprocess
+import sys
+
+
+def main():
+  input_file = sys.argv[1]
+  out_dir = sys.argv[2]
+  keystr = sys.argv[3]
+  propstr = sys.argv[4]
+  bloaty_path = sys.argv[5]
+
+  results = {
+    'key': { },
+    'results': { }
+  }
+
+  props = propstr.split(' ')
+  for i in range(0, len(props), 2):
+    results[props[i]] = props[i+1]
+
+  keys = keystr.split(' ')
+  for i in range(0, len(keys), 2):
+    results['key'][keys[i]] = keys[i+1]
+
+  magic_seperator = '#$%^&*'
+
+  # Human "readable" reports as an FYI.
+  print magic_seperator
+  print 'Report by file, then by symbol with ellided/combined templates'
+  lines = subprocess.check_output([bloaty_path, input_file,
+                                 '-d', 'compileunits,symbols', '-s', 'file',
+                                 '-n', '0', '--tsv', '--demangle=short'])
+  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, input_file,
+                                 '-d', 'compileunits,symbols', '-s', 'file',
+                                 '-n', '0', '--tsv', '--demangle=full'])
+  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, input_file,
+                                 '-d', 'symbols,compileunits', '-s', 'file',
+                                 '-n', '0', '--tsv', '--demangle=short'])
+  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, input_file,
+                                 '-d', 'symbols,compileunits', '-s', 'file',
+                                 '-n', '0', '--tsv', '--demangle=full'])
+  print_skia_lines_symbol_file(lines)
+  print magic_seperator
+
+  r = {
+    # Use the default config as stats about the whole binary
+    'skia_in_flutter' : {
+      'total_size_bytes': grand_total
+    },
+  }
+
+  name = os.path.basename(input_file)
+  results['results'][name] = r
+
+  # Make debugging easier
+  print json.dumps(results, indent=2)
+
+  with open(os.path.join(out_dir, name+'.json'), 'w') as output:
+    output.write(json.dumps(results, indent=2))
+
+
+def bytes_or_kb(num):
+  if num < 1024:
+    return '%d bytes' % num
+  else:
+    return '%1.1f KiB' % (num / 1024.0)
+
+
+def print_skia_lines_file_symbol(lines):
+  lines = lines.split('\n')
+  grand_total = 0
+  sub_total = 0
+  cur_file = ''
+
+  for line in lines:
+    # Line looks like:
+    # ../../third_party/skia/src/file.cpp\tSkTSect<>::intersects()\t1224\t1348
+    parts = line.split('\t')
+    if len(parts) != 4:
+      continue
+    this_file = parts[0]
+    if 'third_party/skia' not in this_file:
+      continue
+    symbol    = parts[1]
+    if '.debug' in symbol:
+      continue
+    # vmsize    = parts[2] Not needed
+    filesize  = int(parts[3])
+
+    if this_file != cur_file:
+      if cur_file != '':
+        print '\t%-100s: %s' % ('Total File Size', bytes_or_kb(sub_total))
+      sub_total = 0
+      cur_file = this_file
+      print this_file.replace('../../third_party/skia', 'skia')
+
+    print '\t%-100s: %s' % (symbol, bytes_or_kb(filesize))
+    sub_total += filesize
+    grand_total += filesize
+
+  print '\t%-100s: %s' % ('Total File Size', bytes_or_kb(sub_total))
+  print '======================================='
+  print 'Grand Total File Size: %s' % bytes_or_kb(grand_total)
+  return grand_total
+
+
+def print_skia_lines_symbol_file(lines):
+  lines = lines.split('\n')
+
+  for line in lines:
+    # Line looks like:
+    # SkTSect<>::intersects()\t../../third_party/skia/src/file.cpp\t1224\t1348
+    parts = line.split('\t')
+    if len(parts) != 4:
+      continue
+    symbol    = parts[0]
+    if 'section' in symbol:
+      continue
+    this_file = parts[1]
+    if 'third_party/skia' not in this_file:
+      continue
+    this_file = this_file.replace('../../third_party/skia', 'skia')
+    # vmsize    = parts[2] Not needed
+    filesize  = int(parts[3])
+
+    print '%-10s: %-80s in %s' % (bytes_or_kb(filesize), symbol, this_file)
+
+
+if '__main__' == __name__:
+  main()
diff --git a/infra/bots/jobs.json b/infra/bots/jobs.json
index b7f8e72..cf10449 100644
--- a/infra/bots/jobs.json
+++ b/infra/bots/jobs.json
@@ -10,6 +10,7 @@
   "Build-Debian9-Clang-arm-Release-Android_Vulkan",
   "Build-Debian9-Clang-arm-Release-Chromebook_GLES",
   "Build-Debian9-Clang-arm-Release-Chromecast",
+  "Build-Debian9-Clang-arm-Release-Flutter_Android",
   "Build-Debian9-Clang-arm64-Debug-Android",
   "Build-Debian9-Clang-arm64-Debug-Android_Vulkan",
   "Build-Debian9-Clang-arm64-Release-Android",
@@ -69,7 +70,6 @@
   "Build-Debian9-GCC-x86_64-Debug",
   "Build-Debian9-GCC-x86_64-Debug-NoGPU",
   "Build-Debian9-GCC-x86_64-Release",
-  "Build-Debian9-GCC-x86_64-Release-Flutter_Android",
   "Build-Debian9-GCC-x86_64-Release-NoGPU",
   "Build-Debian9-GCC-x86_64-Release-SK_CPU_LIMIT_SSE41",
   "Build-Debian9-GCC-x86_64-Release-Shared",
@@ -109,10 +109,11 @@
   "Build-Win-MSVC-x86_64-Debug-Vulkan",
   "Build-Win-MSVC-x86_64-Release",
   "Build-Win-MSVC-x86_64-Release-Vulkan",
+  "BuildStats-Debian9-Clang-arm-Release-Flutter_Android",
+  "BuildStats-Debian9-Clang-x86_64-Release-Mini",
   "BuildStats-Debian9-EMCC-asmjs-Release-PathKit",
   "BuildStats-Debian9-EMCC-wasm-Release-CanvasKit",
   "BuildStats-Debian9-EMCC-wasm-Release-PathKit",
-  "BuildStats-Debian9-Clang-x86_64-Release-Mini",
   "Calmbench-Debian9-Clang-GCE-CPU-AVX2-x86_64-Release-All",
   "Calmbench-Ubuntu17-Clang-Golo-GPU-QuadroP400-x86_64-Release-All",
   "Housekeeper-Nightly-Bookmaker",
diff --git a/infra/bots/recipe_modules/build/examples/full.expected/Build-Debian9-GCC-x86_64-Release-Flutter_Android.json b/infra/bots/recipe_modules/build/examples/full.expected/Build-Debian9-Clang-arm-Release-Flutter_Android.json
similarity index 92%
rename from infra/bots/recipe_modules/build/examples/full.expected/Build-Debian9-GCC-x86_64-Release-Flutter_Android.json
rename to infra/bots/recipe_modules/build/examples/full.expected/Build-Debian9-Clang-arm-Release-Flutter_Android.json
index 7509cf7..a86a6cc 100644
--- a/infra/bots/recipe_modules/build/examples/full.expected/Build-Debian9-GCC-x86_64-Release-Flutter_Android.json
+++ b/infra/bots/recipe_modules/build/examples/full.expected/Build-Debian9-Clang-arm-Release-Flutter_Android.json
@@ -7,7 +7,7 @@
       "--json-output",
       "/path/to/tmp/json",
       "rmtree",
-      "[START_DIR]/cache/work/skia/out/Build-Debian9-GCC-x86_64-Release-Flutter_Android/Release"
+      "[START_DIR]/cache/work/skia/out/Build-Debian9-Clang-arm-Release-Flutter_Android/Release"
     ],
     "cwd": "[START_DIR]/cache/work/src",
     "infra_step": true,
@@ -30,7 +30,7 @@
     "cmd": [
       "ninja",
       "-C",
-      "[START_DIR]/cache/work/skia/out/Build-Debian9-GCC-x86_64-Release-Flutter_Android/Release",
+      "[START_DIR]/cache/work/skia/out/Build-Debian9-Clang-arm-Release-Flutter_Android/Release",
       "-j100"
     ],
     "cwd": "[START_DIR]/cache/work/src",
@@ -45,7 +45,7 @@
       "python",
       "-u",
       "import errno\nimport glob\nimport os\nimport shutil\nimport sys\n\nsrc = sys.argv[1]\ndst = sys.argv[2]\nbuild_products_whitelist = ['bookmaker', 'dm', 'dm.exe', 'dm.app', 'nanobench.app', 'get_images_from_skps', 'get_images_from_skps.exe', 'hello-opencl', 'hello-opencl.exe', 'nanobench', 'nanobench.exe', 'skpbench', 'skpbench.exe', '*.so', '*.dll', '*.dylib', 'skia_launcher', 'skiaserve', 'lib/*.so', 'run_testlab', 'skqp-universal-debug.apk', 'whitelist_devices.json']\n\ntry:\n  os.makedirs(dst)\nexcept OSError as e:\n  if e.errno != errno.EEXIST:\n    raise\n\nfor pattern in build_products_whitelist:\n  path = os.path.join(src, pattern)\n  for f in glob.glob(path):\n    dst_path = os.path.join(dst, os.path.relpath(f, src))\n    if not os.path.isdir(os.path.dirname(dst_path)):\n      os.makedirs(os.path.dirname(dst_path))\n    print 'Copying build product %s to %s' % (f, dst_path)\n    shutil.move(f, dst_path)\n",
-      "[START_DIR]/cache/work/skia/out/Build-Debian9-GCC-x86_64-Release-Flutter_Android/Release",
+      "[START_DIR]/cache/work/skia/out/Build-Debian9-Clang-arm-Release-Flutter_Android/Release",
       "[START_DIR]/[SWARM_OUT_DIR]/out/Release"
     ],
     "infra_step": true,
diff --git a/infra/bots/recipe_modules/build/examples/full.py b/infra/bots/recipe_modules/build/examples/full.py
index fd3b7d2..4b8bd1b 100644
--- a/infra/bots/recipe_modules/build/examples/full.py
+++ b/infra/bots/recipe_modules/build/examples/full.py
@@ -28,6 +28,7 @@
   'Build-Debian9-Clang-arm-Release-Android_API26',
   'Build-Debian9-Clang-arm-Release-Android_ASAN',
   'Build-Debian9-Clang-arm-Release-Chromebook_GLES',
+  'Build-Debian9-Clang-arm-Release-Flutter_Android',
   'Build-Debian9-Clang-x86-devrel-Android_SKQP',
   'Build-Debian9-Clang-x86_64-Debug-Chromebook_GLES',
   'Build-Debian9-Clang-x86_64-Debug-Coverage',
@@ -51,7 +52,6 @@
   'Build-Debian9-GCC-arm-Release-Chromecast',
   'Build-Debian9-GCC-loongson3a-Release',
   'Build-Debian9-GCC-x86_64-Release-ANGLE',
-  'Build-Debian9-GCC-x86_64-Release-Flutter_Android',
   'Build-Debian9-GCC-x86_64-Release-NoGPU',
   'Build-Debian9-GCC-x86_64-Release-Shared',
   'Build-Mac-Clang-arm64-Debug-Android_Vulkan',
diff --git a/infra/bots/recipe_modules/checkout/examples/full.py b/infra/bots/recipe_modules/checkout/examples/full.py
index c103237..d757fb7 100644
--- a/infra/bots/recipe_modules/checkout/examples/full.py
+++ b/infra/bots/recipe_modules/checkout/examples/full.py
@@ -86,7 +86,7 @@
                      patch_storage='gerrit')
   )
 
-  buildername = 'Build-Debian9-GCC-x86_64-Release-Flutter_Android'
+  buildername = 'Build-Debian9-Clang-arm-Release-Flutter_Android'
   yield (
       api.test('flutter_trybot') +
       api.properties(
diff --git a/infra/bots/recipes/compute_buildstats.expected/normal_bot.json b/infra/bots/recipes/compute_buildstats.expected/normal_bot.json
index d13cb2a..f454881 100644
--- a/infra/bots/recipes/compute_buildstats.expected/normal_bot.json
+++ b/infra/bots/recipes/compute_buildstats.expected/normal_bot.json
@@ -258,11 +258,78 @@
       "/path/to/tmp/json",
       "glob",
       "[START_DIR]/build",
-      "*.so"
+      "libflutter.so"
     ],
     "cwd": "[START_DIR]/build",
     "infra_step": true,
-    "name": "find built libraries",
+    "name": "find flutter library",
+    "stdout": "/path/to/tmp/",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@glob@[START_DIR]/build/libflutter.so@@@",
+      "@@@STEP_LOG_END@glob@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "[START_DIR]/cache/work/skia/infra/bots/buildstats/buildstats_flutter.py",
+      "[START_DIR]/build/libflutter.so",
+      "[START_DIR]/[SWARM_OUT_DIR]",
+      "compiler EMCC configuration Release extra_config PathKit os Debian9 target_arch wasm",
+      "gitHash abc123 swarming_bot_id skia-bot-123 swarming_task_id 123456abc",
+      "[START_DIR]/bloaty/bloaty"
+    ],
+    "cwd": "[START_DIR]/cache/work/skia",
+    "env": {
+      "CHROME_HEADLESS": "1",
+      "PATH": "<PATH>:RECIPE_PACKAGE_REPO[depot_tools]"
+    },
+    "name": "Analyze flutter",
+    "stdout": "/path/to/tmp/",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_short@@@@",
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_short@Report A@@@",
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_short@    Total size: 50 bytes@@@",
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_short@@@@",
+      "@@@STEP_LOG_END@bloaty_file_symbol_short@@@",
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_full@@@@",
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_full@Report B@@@",
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_full@    Total size: 60 bytes@@@",
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_full@@@@",
+      "@@@STEP_LOG_END@bloaty_file_symbol_full@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_short@@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_short@Report C@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_short@    Total size: 70 bytes@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_short@@@@",
+      "@@@STEP_LOG_END@bloaty_symbol_file_short@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_full@@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_full@Report D@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_full@    Total size: 80 bytes@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_full@@@@",
+      "@@@STEP_LOG_END@bloaty_symbol_file_full@@@",
+      "@@@STEP_LOG_LINE@perf_json@@@@",
+      "@@@STEP_LOG_LINE@perf_json@{@@@",
+      "@@@STEP_LOG_LINE@perf_json@  \"some\": \"json\"@@@",
+      "@@@STEP_LOG_LINE@perf_json@}@@@",
+      "@@@STEP_LOG_LINE@perf_json@@@@",
+      "@@@STEP_LOG_END@perf_json@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "glob",
+      "[START_DIR]/build",
+      "libskia.so"
+    ],
+    "cwd": "[START_DIR]/build",
+    "infra_step": true,
+    "name": "find skia library",
     "stdout": "/path/to/tmp/",
     "~followup_annotations": [
       "@@@STEP_LOG_LINE@glob@[START_DIR]/build/libskia.so@@@",
diff --git a/infra/bots/recipes/compute_buildstats.expected/trybot.json b/infra/bots/recipes/compute_buildstats.expected/trybot.json
index 64bb10b..4c64bbd 100644
--- a/infra/bots/recipes/compute_buildstats.expected/trybot.json
+++ b/infra/bots/recipes/compute_buildstats.expected/trybot.json
@@ -302,11 +302,78 @@
       "/path/to/tmp/json",
       "glob",
       "[START_DIR]/build",
-      "*.so"
+      "libflutter.so"
     ],
     "cwd": "[START_DIR]/build",
     "infra_step": true,
-    "name": "find built libraries",
+    "name": "find flutter library",
+    "stdout": "/path/to/tmp/",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@glob@[START_DIR]/build/libflutter.so@@@",
+      "@@@STEP_LOG_END@glob@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "[START_DIR]/cache/work/skia/infra/bots/buildstats/buildstats_flutter.py",
+      "[START_DIR]/build/libflutter.so",
+      "[START_DIR]/[SWARM_OUT_DIR]",
+      "compiler EMCC configuration Release extra_config PathKit os Debian9 target_arch wasm",
+      "gitHash abc123 swarming_bot_id skia-bot-123 swarming_task_id 123456abc issue 456789 patchset 12 patch_storage gerrit",
+      "[START_DIR]/bloaty/bloaty"
+    ],
+    "cwd": "[START_DIR]/cache/work/skia",
+    "env": {
+      "CHROME_HEADLESS": "1",
+      "PATH": "<PATH>:RECIPE_PACKAGE_REPO[depot_tools]"
+    },
+    "name": "Analyze flutter",
+    "stdout": "/path/to/tmp/",
+    "~followup_annotations": [
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_short@@@@",
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_short@Report A@@@",
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_short@    Total size: 50 bytes@@@",
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_short@@@@",
+      "@@@STEP_LOG_END@bloaty_file_symbol_short@@@",
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_full@@@@",
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_full@Report B@@@",
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_full@    Total size: 60 bytes@@@",
+      "@@@STEP_LOG_LINE@bloaty_file_symbol_full@@@@",
+      "@@@STEP_LOG_END@bloaty_file_symbol_full@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_short@@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_short@Report C@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_short@    Total size: 70 bytes@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_short@@@@",
+      "@@@STEP_LOG_END@bloaty_symbol_file_short@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_full@@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_full@Report D@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_full@    Total size: 80 bytes@@@",
+      "@@@STEP_LOG_LINE@bloaty_symbol_file_full@@@@",
+      "@@@STEP_LOG_END@bloaty_symbol_file_full@@@",
+      "@@@STEP_LOG_LINE@perf_json@@@@",
+      "@@@STEP_LOG_LINE@perf_json@{@@@",
+      "@@@STEP_LOG_LINE@perf_json@  \"some\": \"json\"@@@",
+      "@@@STEP_LOG_LINE@perf_json@}@@@",
+      "@@@STEP_LOG_LINE@perf_json@@@@",
+      "@@@STEP_LOG_END@perf_json@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "RECIPE_MODULE[recipe_engine::file]/resources/fileutil.py",
+      "--json-output",
+      "/path/to/tmp/json",
+      "glob",
+      "[START_DIR]/build",
+      "libskia.so"
+    ],
+    "cwd": "[START_DIR]/build",
+    "infra_step": true,
+    "name": "find skia library",
     "stdout": "/path/to/tmp/",
     "~followup_annotations": [
       "@@@STEP_LOG_LINE@glob@[START_DIR]/build/libskia.so@@@",
diff --git a/infra/bots/recipes/compute_buildstats.py b/infra/bots/recipes/compute_buildstats.py
index 10bd9c3..9f3ac7d 100644
--- a/infra/bots/recipes/compute_buildstats.py
+++ b/infra/bots/recipes/compute_buildstats.py
@@ -59,9 +59,18 @@
       analyze_web_file(api, checkout_root, out_dir, files)
 
     files = api.file.glob_paths(
-        'find built libraries',
+        'find flutter library',
         bin_dir,
-        '*.so',
+        'libflutter.so',
+        test_data=['libflutter.so'])
+    analyzed += len(files)
+    if len(files):
+      analyze_flutter_lib(api, checkout_root, out_dir, files)
+
+    files = api.file.glob_paths(
+        'find skia library',
+        bin_dir,
+        'libskia.so',
         test_data=['libskia.so'])
     analyzed += len(files)
     if len(files):
@@ -121,6 +130,33 @@
           args=[f, out_dir, keystr, propstr, bloaty_exe])
 
 
+# Get the size of skia in flutter and a few metrics from bloaty
+def analyze_flutter_lib(api, checkout_root, out_dir, files):
+  (keystr, propstr) = keys_and_props(api)
+  bloaty_exe = api.path['start_dir'].join('bloaty', 'bloaty')
+
+  for f in files:
+    skia_dir = checkout_root.join('skia')
+    with api.context(cwd=skia_dir):
+      script = skia_dir.join('infra', 'bots', 'buildstats',
+                             'buildstats_flutter.py')
+      step_data = api.run(api.python, 'Analyze flutter', script=script,
+                         args=[f, out_dir, keystr, propstr, bloaty_exe],
+                         stdout=api.raw_io.output())
+      if step_data and step_data.stdout:
+        magic_seperator = '#$%^&*'
+        sections = step_data.stdout.split(magic_seperator)
+        result = api.step.active_result
+        logs = result.presentation.logs
+        # Skip section 0 because it's everything before first print,
+        # which is probably the empty string.
+        logs['bloaty_file_symbol_short'] = sections[1].split('\n')
+        logs['bloaty_file_symbol_full']  = sections[2].split('\n')
+        logs['bloaty_symbol_file_short'] = sections[3].split('\n')
+        logs['bloaty_symbol_file_full']  = sections[4].split('\n')
+        logs['perf_json'] = sections[5].split('\n')
+
+
 def GenTests(api):
   builder = 'BuildStats-Debian9-EMCC-wasm-Release-PathKit'
   yield (
@@ -130,10 +166,12 @@
                    revision='abc123',
                    swarm_out_dir='[SWARM_OUT_DIR]',
                    path_config='kitchen') +
-      api.step_data('get swarming bot id',
-          stdout=api.raw_io.output('skia-bot-123')) +
-      api.step_data('get swarming task id',
-          stdout=api.raw_io.output('123456abc'))
+    api.step_data('get swarming bot id',
+        stdout=api.raw_io.output('skia-bot-123')) +
+    api.step_data('get swarming task id',
+        stdout=api.raw_io.output('123456abc')) +
+    api.step_data('Analyze flutter',
+        stdout=api.raw_io.output(sample_output))
   )
 
   yield (
@@ -153,5 +191,26 @@
         buildername=builder,
         gerrit_project='skia',
         gerrit_url='https://skia-review.googlesource.com/',
-      )
+      ) +
+    api.step_data('Analyze flutter',
+          stdout=api.raw_io.output(sample_output))
   )
+
+sample_output = """
+#$%^&*
+Report A
+    Total size: 50 bytes
+#$%^&*
+Report B
+    Total size: 60 bytes
+#$%^&*
+Report C
+    Total size: 70 bytes
+#$%^&*
+Report D
+    Total size: 80 bytes
+#$%^&*
+{
+  "some": "json"
+}
+"""
diff --git a/infra/bots/tasks.json b/infra/bots/tasks.json
index 60a250e..669f071 100755
--- a/infra/bots/tasks.json
+++ b/infra/bots/tasks.json
@@ -55,6 +55,12 @@
         "Build-Debian9-Clang-arm-Release-Chromecast"
       ]
     },
+    "Build-Debian9-Clang-arm-Release-Flutter_Android": {
+      "tasks": [
+        "Build-Debian9-Clang-arm-Release-Flutter_Android"
+      ],
+      "trigger": "master"
+    },
     "Build-Debian9-Clang-arm64-Debug-Android": {
       "tasks": [
         "Build-Debian9-Clang-arm64-Debug-Android"
@@ -351,12 +357,6 @@
         "Build-Debian9-GCC-x86_64-Release"
       ]
     },
-    "Build-Debian9-GCC-x86_64-Release-Flutter_Android": {
-      "tasks": [
-        "Build-Debian9-GCC-x86_64-Release-Flutter_Android"
-      ],
-      "trigger": "master"
-    },
     "Build-Debian9-GCC-x86_64-Release-NoGPU": {
       "tasks": [
         "Build-Debian9-GCC-x86_64-Release-NoGPU"
@@ -554,6 +554,12 @@
         "Build-Win-MSVC-x86_64-Release-Vulkan"
       ]
     },
+    "BuildStats-Debian9-Clang-arm-Release-Flutter_Android": {
+      "tasks": [
+        "Upload-BuildStats-Debian9-Clang-arm-Release-Flutter_Android"
+      ],
+      "trigger": "master"
+    },
     "BuildStats-Debian9-Clang-x86_64-Release-Mini": {
       "tasks": [
         "Upload-BuildStats-Debian9-Clang-x86_64-Release-Mini"
@@ -4331,6 +4337,131 @@
       ],
       "service_account": "skia-external-compile-tasks@skia-swarming-bots.iam.gserviceaccount.com"
     },
+    "Build-Debian9-Clang-arm-Release-Flutter_Android": {
+      "caches": [
+        {
+          "name": "vpython",
+          "path": "cache/vpython"
+        },
+        {
+          "name": "git",
+          "path": "cache/git"
+        },
+        {
+          "name": "git_cache",
+          "path": "cache/git_cache"
+        },
+        {
+          "name": "work",
+          "path": "cache/work"
+        }
+      ],
+      "cipd_packages": [
+        {
+          "name": "infra/tools/luci/kitchen/${platform}",
+          "path": ".",
+          "version": "git_revision:546aae39f1fb9dce9add528e2011afa574535ecd"
+        },
+        {
+          "name": "infra/tools/luci-auth/${platform}",
+          "path": "cipd_bin_packages",
+          "version": "git_revision:e1abc57be62d198b5c2f487bfb2fa2d2eb0e867c"
+        },
+        {
+          "name": "infra/tools/luci/vpython/${platform}",
+          "path": "cipd_bin_packages",
+          "version": "git_revision:b6cdec8586c9f8d3d728b1bc0bd4331330ba66fc"
+        },
+        {
+          "name": "infra/git/${platform}",
+          "path": "cipd_bin_packages",
+          "version": "version:2.17.1.chromium15"
+        },
+        {
+          "name": "infra/tools/git/${platform}",
+          "path": "cipd_bin_packages",
+          "version": "git_revision:0ae21738597e5601ba90372315145fec18582fc4"
+        },
+        {
+          "name": "infra/tools/luci/git-credential-luci/${platform}",
+          "path": "cipd_bin_packages",
+          "version": "git_revision:e1abc57be62d198b5c2f487bfb2fa2d2eb0e867c"
+        }
+      ],
+      "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",
+        "compile",
+        "-properties",
+        "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildbucket_build_id\":\"<(BUILDBUCKET_BUILD_ID)\",\"buildername\":\"Build-Debian9-Clang-arm-Release-Flutter_Android\",\"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\":\"build\"}",
+        "-logdog-annotation-url",
+        "logdog://logs.chromium.org/skia/<(TASK_ID)/+/annotations"
+      ],
+      "dependencies": [
+        "Housekeeper-PerCommit-BundleRecipes",
+        "Housekeeper-PerCommit-IsolateAndroidNDKLinux"
+      ],
+      "dimensions": [
+        "cpu:x86-64-Haswell_GCE",
+        "gpu:none",
+        "machine_type:n1-highcpu-64",
+        "os:Debian-9.4",
+        "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": 1,
+      "outputs": [
+        "build"
+      ],
+      "service_account": "skia-external-compile-tasks@skia-swarming-bots.iam.gserviceaccount.com"
+    },
     "Build-Debian9-Clang-arm64-Debug-Android": {
       "caches": [
         {
@@ -11874,131 +12005,6 @@
       ],
       "service_account": "skia-external-compile-tasks@skia-swarming-bots.iam.gserviceaccount.com"
     },
-    "Build-Debian9-GCC-x86_64-Release-Flutter_Android": {
-      "caches": [
-        {
-          "name": "vpython",
-          "path": "cache/vpython"
-        },
-        {
-          "name": "git",
-          "path": "cache/git"
-        },
-        {
-          "name": "git_cache",
-          "path": "cache/git_cache"
-        },
-        {
-          "name": "work",
-          "path": "cache/work"
-        }
-      ],
-      "cipd_packages": [
-        {
-          "name": "infra/tools/luci/kitchen/${platform}",
-          "path": ".",
-          "version": "git_revision:546aae39f1fb9dce9add528e2011afa574535ecd"
-        },
-        {
-          "name": "infra/tools/luci-auth/${platform}",
-          "path": "cipd_bin_packages",
-          "version": "git_revision:e1abc57be62d198b5c2f487bfb2fa2d2eb0e867c"
-        },
-        {
-          "name": "infra/tools/luci/vpython/${platform}",
-          "path": "cipd_bin_packages",
-          "version": "git_revision:b6cdec8586c9f8d3d728b1bc0bd4331330ba66fc"
-        },
-        {
-          "name": "infra/git/${platform}",
-          "path": "cipd_bin_packages",
-          "version": "version:2.17.1.chromium15"
-        },
-        {
-          "name": "infra/tools/git/${platform}",
-          "path": "cipd_bin_packages",
-          "version": "git_revision:0ae21738597e5601ba90372315145fec18582fc4"
-        },
-        {
-          "name": "infra/tools/luci/git-credential-luci/${platform}",
-          "path": "cipd_bin_packages",
-          "version": "git_revision:e1abc57be62d198b5c2f487bfb2fa2d2eb0e867c"
-        }
-      ],
-      "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",
-        "compile",
-        "-properties",
-        "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildbucket_build_id\":\"<(BUILDBUCKET_BUILD_ID)\",\"buildername\":\"Build-Debian9-GCC-x86_64-Release-Flutter_Android\",\"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\":\"build\"}",
-        "-logdog-annotation-url",
-        "logdog://logs.chromium.org/skia/<(TASK_ID)/+/annotations"
-      ],
-      "dependencies": [
-        "Housekeeper-PerCommit-BundleRecipes",
-        "Housekeeper-PerCommit-IsolateAndroidNDKLinux"
-      ],
-      "dimensions": [
-        "cpu:x86-64-Haswell_GCE",
-        "gpu:none",
-        "machine_type:n1-highcpu-64",
-        "os:Debian-9.4",
-        "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": 1,
-      "outputs": [
-        "build"
-      ],
-      "service_account": "skia-external-compile-tasks@skia-swarming-bots.iam.gserviceaccount.com"
-    },
     "Build-Debian9-GCC-x86_64-Release-NoGPU": {
       "caches": [
         {
@@ -17183,6 +17189,107 @@
       ],
       "service_account": "skia-external-compile-tasks@skia-swarming-bots.iam.gserviceaccount.com"
     },
+    "BuildStats-Debian9-Clang-arm-Release-Flutter_Android": {
+      "caches": [
+        {
+          "name": "vpython",
+          "path": "cache/vpython"
+        }
+      ],
+      "cipd_packages": [
+        {
+          "name": "infra/tools/luci/kitchen/${platform}",
+          "path": ".",
+          "version": "git_revision:546aae39f1fb9dce9add528e2011afa574535ecd"
+        },
+        {
+          "name": "infra/tools/luci-auth/${platform}",
+          "path": "cipd_bin_packages",
+          "version": "git_revision:e1abc57be62d198b5c2f487bfb2fa2d2eb0e867c"
+        },
+        {
+          "name": "infra/tools/luci/vpython/${platform}",
+          "path": "cipd_bin_packages",
+          "version": "git_revision:b6cdec8586c9f8d3d728b1bc0bd4331330ba66fc"
+        },
+        {
+          "name": "skia/bots/bloaty",
+          "path": "bloaty",
+          "version": "version:0"
+        }
+      ],
+      "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",
+        "compute_buildstats",
+        "-properties",
+        "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildbucket_build_id\":\"<(BUILDBUCKET_BUILD_ID)\",\"buildername\":\"BuildStats-Debian9-Clang-arm-Release-Flutter_Android\",\"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\"}",
+        "-logdog-annotation-url",
+        "logdog://logs.chromium.org/skia/<(TASK_ID)/+/annotations"
+      ],
+      "dependencies": [
+        "Housekeeper-PerCommit-BundleRecipes",
+        "Build-Debian9-Clang-arm-Release-Flutter_Android"
+      ],
+      "dimensions": [
+        "cpu:x86-64-Haswell_GCE",
+        "gpu:none",
+        "machine_type:n1-highcpu-64",
+        "os:Debian-9.4",
+        "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",
+      "outputs": [
+        "perf"
+      ]
+    },
     "BuildStats-Debian9-Clang-x86_64-Release-Mini": {
       "caches": [
         {
@@ -68540,6 +68647,105 @@
       "isolate": "swarm_recipe.isolate",
       "service_account": "skia-external-binary-uploader@skia-swarming-bots.iam.gserviceaccount.com"
     },
+    "Upload-BuildStats-Debian9-Clang-arm-Release-Flutter_Android": {
+      "caches": [
+        {
+          "name": "vpython",
+          "path": "cache/vpython"
+        }
+      ],
+      "cipd_packages": [
+        {
+          "name": "infra/tools/luci/kitchen/${platform}",
+          "path": ".",
+          "version": "git_revision:546aae39f1fb9dce9add528e2011afa574535ecd"
+        },
+        {
+          "name": "infra/tools/luci-auth/${platform}",
+          "path": "cipd_bin_packages",
+          "version": "git_revision:e1abc57be62d198b5c2f487bfb2fa2d2eb0e867c"
+        },
+        {
+          "name": "infra/tools/luci/vpython/${platform}",
+          "path": "cipd_bin_packages",
+          "version": "git_revision:b6cdec8586c9f8d3d728b1bc0bd4331330ba66fc"
+        },
+        {
+          "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_buildstats_results",
+        "-properties",
+        "{\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"buildbucket_build_id\":\"<(BUILDBUCKET_BUILD_ID)\",\"buildername\":\"BuildStats-Debian9-Clang-arm-Release-Flutter_Android\",\"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\"}",
+        "-logdog-annotation-url",
+        "logdog://logs.chromium.org/skia/<(TASK_ID)/+/annotations"
+      ],
+      "dependencies": [
+        "Housekeeper-PerCommit-BundleRecipes",
+        "BuildStats-Debian9-Clang-arm-Release-Flutter_Android"
+      ],
+      "dimensions": [
+        "cpu:x86-64-Haswell_GCE",
+        "gpu:none",
+        "machine_type:n1-highmem-2",
+        "os:Debian-9.4",
+        "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",
+      "service_account": "skia-external-nano-uploader@skia-swarming-bots.iam.gserviceaccount.com"
+    },
     "Upload-BuildStats-Debian9-Clang-x86_64-Release-Mini": {
       "caches": [
         {