Scale extra CPUs to powersave during nanobench.

This scaling logic correctly accounts for some devices
which have multiple CPUs.  Previously, we were scaling
the smaller of these CPUs, which likely had a negative
impact on nanobench, given nanobench was single threaded
and the CPUs weren't allowed to idle much (because we
set the CPU).

This CL sets those additional CPUs to powersave when we run
nanobench and then correctly scales down the beefier
CPU we want to run nanobench on.

For DM, we just run it in ondemand mode, which will
hopefully be "as fast as possible", but allow the CPU
governor to scale down if overheating becomes a problem.

Bug: skia:7378
notry=TRUE
Change-Id: I45ca5d9fb32182233d1b2d094842c879f2b84da4
Reviewed-on: https://skia-review.googlesource.com/83240
Commit-Queue: Kevin Lubick <kjlubick@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
diff --git a/infra/bots/recipes/perf.expected/Perf-Android-Clang-Nexus5-GPU-Adreno330-arm-Debug-All-Android.json b/infra/bots/recipes/perf.expected/Perf-Android-Clang-Nexus5-GPU-Adreno330-arm-Debug-All-Android.json
index dcbb214..b692d3e 100644
--- a/infra/bots/recipes/perf.expected/Perf-Android-Clang-Nexus5-GPU-Adreno330-arm-Debug-All-Android.json
+++ b/infra/bots/recipes/perf.expected/Perf-Android-Clang-Nexus5-GPU-Adreno330-arm-Debug-All-Android.json
@@ -540,10 +540,10 @@
     "cmd": [
       "python",
       "-u",
-      "\nimport os\nimport subprocess\nimport sys\nimport time\nADB = sys.argv[1]\nmodel = sys.argv[2]\ntarget_percent = float(sys.argv[3])\nlog = subprocess.check_output([ADB, 'root'])\n# check for message like 'adbd cannot run as root in production builds'\nprint log\nif 'cannot' in log:\n  raise Exception('adb root failed')\n\nif model == 'Nexus7':\n  # Nexus7 claims to support 1300000, but only really allows 1200000\n  available_freqs = [51000, 102000, 204000, 340000, 475000, 640000, 760000,\n                     860000, 1000000, 1100000, 1200000]\nelse:\n  # Temporary logging to get a sense of what devices have multiple cpus\n  try:\n    print subprocess.check_output([ADB, 'shell', 'cat ',\n        '/sys/devices/system/cpu/cpu?/cpufreq/affected_cpus'])\n    print subprocess.check_output([ADB, 'shell', 'cat ',\n        '/sys/devices/system/cpu/cpu?/cpufreq/scaling_available_frequencies'])\n  except Exception as e:\n    print e.output.strip()\n  # Most devices give a list of their available frequencies.\n  available_freqs = subprocess.check_output([ADB, 'shell', 'cat '\n      '/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies'])\n\n  # Check for message like '/system/bin/sh: file not found'\n  if available_freqs and '/system/bin/sh' not in available_freqs:\n    available_freqs = sorted(\n        int(i) for i in available_freqs.strip().split())\n  else:\n    raise Exception('Could not get list of available frequencies: %s' %\n                    available_freqs)\n\nmaxfreq = available_freqs[-1]\ntarget = int(round(maxfreq * target_percent))\nfreq = maxfreq\nfor f in reversed(available_freqs):\n  if f <= target:\n    freq = f\n    break\n\nprint 'Setting frequency to %d' % freq\n\nsubprocess.check_output([ADB, 'shell', 'echo \"userspace\" > '\n    '/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor'])\n# If scaling_max_freq is lower than our attempted setting, it won't take.\n# We must set min first, because if we try to set max to be less than min\n# (which sometimes happens after certain devices reboot) it returns a\n# perplexing permissions error.\nsubprocess.check_output([ADB, 'shell', 'echo 0 > '\n    '/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq'])\nsubprocess.check_output([ADB, 'shell', 'echo %d > '\n    '/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq' % freq])\nsubprocess.check_output([ADB, 'shell', 'echo %d > '\n    '/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed' % freq])\ntime.sleep(5)\nactual_freq = subprocess.check_output([ADB, 'shell', 'cat '\n    '/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq']).strip()\nif actual_freq != str(freq):\n  raise Exception('(actual, expected) (%s, %d)'\n                  % (actual_freq, freq))\n",
+      "\nimport os\nimport subprocess\nimport sys\nimport time\nADB = sys.argv[1]\ncpu = int(sys.argv[2])\ngov = sys.argv[3]\n\nlog = subprocess.check_output([ADB, 'root'])\n# check for message like 'adbd cannot run as root in production builds'\nprint log\nif 'cannot' in log:\n  raise Exception('adb root failed')\n\nsubprocess.check_output([ADB, 'shell', 'echo \"%s\" > '\n    '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor' % (gov, cpu)])\nactual_gov = subprocess.check_output([ADB, 'shell', 'cat '\n    '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor' % cpu]).strip()\nif actual_gov != str(gov):\n  raise Exception('(actual, expected) (%s, %d)'\n                  % (actual_gov, gov))\n",
       "/usr/bin/adb.1.0.35",
-      "Nexus5",
-      "0.6"
+      "0",
+      "userspace"
     ],
     "env": {
       "BUILDTYPE": "Debug",
@@ -552,7 +552,7 @@
       "SKIA_OUT": "[START_DIR]/out"
     },
     "infra_step": true,
-    "name": "Scale CPU to 0.600000",
+    "name": "Set CPU 0's governor to userspace",
     "timeout": 30,
     "~followup_annotations": [
       "@@@STEP_LOG_LINE@python.inline@@@@",
@@ -561,38 +561,71 @@
       "@@@STEP_LOG_LINE@python.inline@import sys@@@",
       "@@@STEP_LOG_LINE@python.inline@import time@@@",
       "@@@STEP_LOG_LINE@python.inline@ADB = sys.argv[1]@@@",
-      "@@@STEP_LOG_LINE@python.inline@model = sys.argv[2]@@@",
-      "@@@STEP_LOG_LINE@python.inline@target_percent = float(sys.argv[3])@@@",
+      "@@@STEP_LOG_LINE@python.inline@cpu = int(sys.argv[2])@@@",
+      "@@@STEP_LOG_LINE@python.inline@gov = sys.argv[3]@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
       "@@@STEP_LOG_LINE@python.inline@log = subprocess.check_output([ADB, 'root'])@@@",
       "@@@STEP_LOG_LINE@python.inline@# check for message like 'adbd cannot run as root in production builds'@@@",
       "@@@STEP_LOG_LINE@python.inline@print log@@@",
       "@@@STEP_LOG_LINE@python.inline@if 'cannot' in log:@@@",
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('adb root failed')@@@",
       "@@@STEP_LOG_LINE@python.inline@@@@",
-      "@@@STEP_LOG_LINE@python.inline@if model == 'Nexus7':@@@",
-      "@@@STEP_LOG_LINE@python.inline@  # Nexus7 claims to support 1300000, but only really allows 1200000@@@",
-      "@@@STEP_LOG_LINE@python.inline@  available_freqs = [51000, 102000, 204000, 340000, 475000, 640000, 760000,@@@",
-      "@@@STEP_LOG_LINE@python.inline@                     860000, 1000000, 1100000, 1200000]@@@",
-      "@@@STEP_LOG_LINE@python.inline@else:@@@",
-      "@@@STEP_LOG_LINE@python.inline@  # Temporary logging to get a sense of what devices have multiple cpus@@@",
-      "@@@STEP_LOG_LINE@python.inline@  try:@@@",
-      "@@@STEP_LOG_LINE@python.inline@    print subprocess.check_output([ADB, 'shell', 'cat ',@@@",
-      "@@@STEP_LOG_LINE@python.inline@        '/sys/devices/system/cpu/cpu?/cpufreq/affected_cpus'])@@@",
-      "@@@STEP_LOG_LINE@python.inline@    print subprocess.check_output([ADB, 'shell', 'cat ',@@@",
-      "@@@STEP_LOG_LINE@python.inline@        '/sys/devices/system/cpu/cpu?/cpufreq/scaling_available_frequencies'])@@@",
-      "@@@STEP_LOG_LINE@python.inline@  except Exception as e:@@@",
-      "@@@STEP_LOG_LINE@python.inline@    print e.output.strip()@@@",
-      "@@@STEP_LOG_LINE@python.inline@  # Most devices give a list of their available frequencies.@@@",
-      "@@@STEP_LOG_LINE@python.inline@  available_freqs = subprocess.check_output([ADB, 'shell', 'cat '@@@",
-      "@@@STEP_LOG_LINE@python.inline@      '/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies'])@@@",
+      "@@@STEP_LOG_LINE@python.inline@subprocess.check_output([ADB, 'shell', 'echo \"%s\" > '@@@",
+      "@@@STEP_LOG_LINE@python.inline@    '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor' % (gov, cpu)])@@@",
+      "@@@STEP_LOG_LINE@python.inline@actual_gov = subprocess.check_output([ADB, 'shell', 'cat '@@@",
+      "@@@STEP_LOG_LINE@python.inline@    '/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor' % cpu]).strip()@@@",
+      "@@@STEP_LOG_LINE@python.inline@if actual_gov != str(gov):@@@",
+      "@@@STEP_LOG_LINE@python.inline@  raise Exception('(actual, expected) (%s, %d)'@@@",
+      "@@@STEP_LOG_LINE@python.inline@                  % (actual_gov, gov))@@@",
+      "@@@STEP_LOG_END@python.inline@@@"
+    ]
+  },
+  {
+    "cmd": [
+      "python",
+      "-u",
+      "\nimport os\nimport subprocess\nimport sys\nimport time\nADB = sys.argv[1]\ntarget_percent = float(sys.argv[2])\ncpu = int(sys.argv[3])\nlog = subprocess.check_output([ADB, 'root'])\n# check for message like 'adbd cannot run as root in production builds'\nprint log\nif 'cannot' in log:\n  raise Exception('adb root failed')\n\nroot = '/sys/devices/system/cpu/cpu%d/cpufreq' %cpu\n\n# All devices we test on give a list of their available frequencies.\navailable_freqs = subprocess.check_output([ADB, 'shell',\n    'cat %s/scaling_available_frequencies' % root])\n\n# Check for message like '/system/bin/sh: file not found'\nif available_freqs and '/system/bin/sh' not in available_freqs:\n  available_freqs = sorted(\n      int(i) for i in available_freqs.strip().split())\nelse:\n  raise Exception('Could not get list of available frequencies: %s' %\n                  available_freqs)\n\nmaxfreq = available_freqs[-1]\ntarget = int(round(maxfreq * target_percent))\nfreq = maxfreq\nfor f in reversed(available_freqs):\n  if f <= target:\n    freq = f\n    break\n\nprint 'Setting frequency to %d' % freq\n\n# If scaling_max_freq is lower than our attempted setting, it won't take.\n# We must set min first, because if we try to set max to be less than min\n# (which sometimes happens after certain devices reboot) it returns a\n# perplexing permissions error.\nsubprocess.check_output([ADB, 'shell', 'echo 0 > '\n    '%s/scaling_min_freq' % root])\nsubprocess.check_output([ADB, 'shell', 'echo %d > '\n    '%s/scaling_max_freq' % (freq, root)])\nsubprocess.check_output([ADB, 'shell', 'echo %d > '\n    '%s/scaling_setspeed' % (freq, root)])\ntime.sleep(5)\nactual_freq = subprocess.check_output([ADB, 'shell', 'cat '\n    '%s/scaling_cur_freq' % root]).strip()\nif actual_freq != str(freq):\n  raise Exception('(actual, expected) (%s, %d)'\n                  % (actual_freq, freq))\n",
+      "/usr/bin/adb.1.0.35",
+      "0.6",
+      "0"
+    ],
+    "env": {
+      "BUILDTYPE": "Debug",
+      "CHROME_HEADLESS": "1",
+      "PATH": "<PATH>:RECIPE_PACKAGE_REPO[depot_tools]",
+      "SKIA_OUT": "[START_DIR]/out"
+    },
+    "infra_step": true,
+    "name": "Scale CPU 0 to 0.600000",
+    "timeout": 30,
+    "~followup_annotations": [
       "@@@STEP_LOG_LINE@python.inline@@@@",
-      "@@@STEP_LOG_LINE@python.inline@  # Check for message like '/system/bin/sh: file not found'@@@",
-      "@@@STEP_LOG_LINE@python.inline@  if available_freqs and '/system/bin/sh' not in available_freqs:@@@",
-      "@@@STEP_LOG_LINE@python.inline@    available_freqs = sorted(@@@",
-      "@@@STEP_LOG_LINE@python.inline@        int(i) for i in available_freqs.strip().split())@@@",
-      "@@@STEP_LOG_LINE@python.inline@  else:@@@",
-      "@@@STEP_LOG_LINE@python.inline@    raise Exception('Could not get list of available frequencies: %s' %@@@",
-      "@@@STEP_LOG_LINE@python.inline@                    available_freqs)@@@",
+      "@@@STEP_LOG_LINE@python.inline@import os@@@",
+      "@@@STEP_LOG_LINE@python.inline@import subprocess@@@",
+      "@@@STEP_LOG_LINE@python.inline@import sys@@@",
+      "@@@STEP_LOG_LINE@python.inline@import time@@@",
+      "@@@STEP_LOG_LINE@python.inline@ADB = sys.argv[1]@@@",
+      "@@@STEP_LOG_LINE@python.inline@target_percent = float(sys.argv[2])@@@",
+      "@@@STEP_LOG_LINE@python.inline@cpu = int(sys.argv[3])@@@",
+      "@@@STEP_LOG_LINE@python.inline@log = subprocess.check_output([ADB, 'root'])@@@",
+      "@@@STEP_LOG_LINE@python.inline@# check for message like 'adbd cannot run as root in production builds'@@@",
+      "@@@STEP_LOG_LINE@python.inline@print log@@@",
+      "@@@STEP_LOG_LINE@python.inline@if 'cannot' in log:@@@",
+      "@@@STEP_LOG_LINE@python.inline@  raise Exception('adb root failed')@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@root = '/sys/devices/system/cpu/cpu%d/cpufreq' %cpu@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@# All devices we test on give a list of their available frequencies.@@@",
+      "@@@STEP_LOG_LINE@python.inline@available_freqs = subprocess.check_output([ADB, 'shell',@@@",
+      "@@@STEP_LOG_LINE@python.inline@    'cat %s/scaling_available_frequencies' % root])@@@",
+      "@@@STEP_LOG_LINE@python.inline@@@@",
+      "@@@STEP_LOG_LINE@python.inline@# Check for message like '/system/bin/sh: file not found'@@@",
+      "@@@STEP_LOG_LINE@python.inline@if available_freqs and '/system/bin/sh' not in available_freqs:@@@",
+      "@@@STEP_LOG_LINE@python.inline@  available_freqs = sorted(@@@",
+      "@@@STEP_LOG_LINE@python.inline@      int(i) for i in available_freqs.strip().split())@@@",
+      "@@@STEP_LOG_LINE@python.inline@else:@@@",
+      "@@@STEP_LOG_LINE@python.inline@  raise Exception('Could not get list of available frequencies: %s' %@@@",
+      "@@@STEP_LOG_LINE@python.inline@                  available_freqs)@@@",
       "@@@STEP_LOG_LINE@python.inline@@@@",
       "@@@STEP_LOG_LINE@python.inline@maxfreq = available_freqs[-1]@@@",
       "@@@STEP_LOG_LINE@python.inline@target = int(round(maxfreq * target_percent))@@@",
@@ -604,21 +637,19 @@
       "@@@STEP_LOG_LINE@python.inline@@@@",
       "@@@STEP_LOG_LINE@python.inline@print 'Setting frequency to %d' % freq@@@",
       "@@@STEP_LOG_LINE@python.inline@@@@",
-      "@@@STEP_LOG_LINE@python.inline@subprocess.check_output([ADB, 'shell', 'echo \"userspace\" > '@@@",
-      "@@@STEP_LOG_LINE@python.inline@    '/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor'])@@@",
       "@@@STEP_LOG_LINE@python.inline@# If scaling_max_freq is lower than our attempted setting, it won't take.@@@",
       "@@@STEP_LOG_LINE@python.inline@# We must set min first, because if we try to set max to be less than min@@@",
       "@@@STEP_LOG_LINE@python.inline@# (which sometimes happens after certain devices reboot) it returns a@@@",
       "@@@STEP_LOG_LINE@python.inline@# perplexing permissions error.@@@",
       "@@@STEP_LOG_LINE@python.inline@subprocess.check_output([ADB, 'shell', 'echo 0 > '@@@",
-      "@@@STEP_LOG_LINE@python.inline@    '/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq'])@@@",
+      "@@@STEP_LOG_LINE@python.inline@    '%s/scaling_min_freq' % root])@@@",
       "@@@STEP_LOG_LINE@python.inline@subprocess.check_output([ADB, 'shell', 'echo %d > '@@@",
-      "@@@STEP_LOG_LINE@python.inline@    '/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq' % freq])@@@",
+      "@@@STEP_LOG_LINE@python.inline@    '%s/scaling_max_freq' % (freq, root)])@@@",
       "@@@STEP_LOG_LINE@python.inline@subprocess.check_output([ADB, 'shell', 'echo %d > '@@@",
-      "@@@STEP_LOG_LINE@python.inline@    '/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed' % freq])@@@",
+      "@@@STEP_LOG_LINE@python.inline@    '%s/scaling_setspeed' % (freq, root)])@@@",
       "@@@STEP_LOG_LINE@python.inline@time.sleep(5)@@@",
       "@@@STEP_LOG_LINE@python.inline@actual_freq = subprocess.check_output([ADB, 'shell', 'cat '@@@",
-      "@@@STEP_LOG_LINE@python.inline@    '/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq']).strip()@@@",
+      "@@@STEP_LOG_LINE@python.inline@    '%s/scaling_cur_freq' % root]).strip()@@@",
       "@@@STEP_LOG_LINE@python.inline@if actual_freq != str(freq):@@@",
       "@@@STEP_LOG_LINE@python.inline@  raise Exception('(actual, expected) (%s, %d)'@@@",
       "@@@STEP_LOG_LINE@python.inline@                  % (actual_freq, freq))@@@",