aboutsummaryrefslogtreecommitdiff
path: root/crosperf
diff options
context:
space:
mode:
authorDenis Nikitin <denik@google.com>2019-09-04 07:51:52 -0700
committerDenis Nikitin <denik@chromium.org>2019-09-10 05:34:59 +0000
commit1acae417eaeda7640327721f7226bf1e0ea960ed (patch)
tree8b50e7a911afe483a715f86778513d5afb43cbe8 /crosperf
parent9d114045ddf617b67fd7af5aaccd0b5dcd4282ea (diff)
downloadtoolchain-utils-1acae417eaeda7640327721f7226bf1e0ea960ed.tar.gz
crosperf: Setup CPU configuration based on 'cpu_usage'.
Based on dut_config['cpu_usage'] setup DUT to use big or little cores only on ARM platform. Ignore 'cpu_usage' if setup is invalid for targeted platform. For example 'big_only" on Intel or ARM w/o big/little support. BUG=chromium:966514 TEST=Unitest and local HW tests passed. Cq-Depend: chromium:1778515 Change-Id: Ida457a1ceaf20c4dcbb8d40334a2423836999574 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/1783849 Reviewed-by: Caroline Tice <cmtice@chromium.org> Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org> Tested-by: Denis Nikitin <denik@chromium.org>
Diffstat (limited to 'crosperf')
-rw-r--r--crosperf/suite_runner.py122
-rwxr-xr-xcrosperf/suite_runner_unittest.py189
2 files changed, 310 insertions, 1 deletions
diff --git a/crosperf/suite_runner.py b/crosperf/suite_runner.py
index 2831b9bd..d5d6c2c7 100644
--- a/crosperf/suite_runner.py
+++ b/crosperf/suite_runner.py
@@ -8,6 +8,7 @@
from __future__ import print_function
import os
+import re
import shlex
import time
@@ -80,6 +81,7 @@ class SuiteRunner(object):
if not self.enable_aslr:
self.DisableASLR(machine, label.chromeos_root)
self.PinGovernorExecutionFrequencies(machine, label.chromeos_root)
+ self.SetupCpuUsage(machine, label.chromeos_root)
if benchmark.suite == 'telemetry_Crosperf':
self.DecreaseWaitTime(machine, label.chromeos_root)
ret_tup = self.Telemetry_Crosperf_Run(machine, label, benchmark,
@@ -173,6 +175,126 @@ class SuiteRunner(object):
self.logger.LogFatalIf(
ret, 'Could not pin frequencies on machine: %s' % machine_name)
+ def SetupCpuUsage(self, machine_name, chromeos_root):
+ """Setup CPU usage.
+
+ Based on self.dut_config['cpu_usage'] configure CPU cores
+ utilization.
+ """
+
+ if (self.dut_config['cpu_usage'] == 'big_only' or
+ self.dut_config['cpu_usage'] == 'little_only'):
+ ret, arch, _ = self._ce.CrosRunCommandWOutput(
+ 'uname -m', machine=machine_name, chromeos_root=chromeos_root)
+ self.logger.LogFatalIf(
+ ret, 'Setup CPU failed. Could not retrieve architecture model.')
+
+ if arch.lower().startswith('arm') or arch.lower().startswith('aarch64'):
+ self.SetupArmCores(machine_name, chromeos_root)
+
+ def SetupArmCores(self, machine_name, chromeos_root):
+ """Setup ARM big/little cores."""
+
+ # CPU implemeters/part numbers of big/LITTLE CPU.
+ # Format: dict(CPU implementer: set(CPU part numbers))
+ LITTLE_CORES = {
+ '0x41': {
+ '0xd01', # Cortex A32
+ '0xd03', # Cortex A53
+ '0xd04', # Cortex A35
+ '0xd05', # Cortex A55
+ },
+ }
+ BIG_CORES = {
+ '0x41': {
+ '0xd07', # Cortex A57
+ '0xd08', # Cortex A72
+ '0xd09', # Cortex A73
+ '0xd0a', # Cortex A75
+ '0xd0b', # Cortex A76
+ },
+ }
+
+ # Values of CPU Implementer and CPU part number are exposed by cpuinfo.
+ # Format:
+ # =================
+ # processor : 0
+ # model name : ARMv8 Processor rev 4 (v8l)
+ # BogoMIPS : 48.00
+ # Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4
+ # CPU implementer : 0x41
+ # CPU architecture: 8
+ # CPU variant : 0x0
+ # CPU part : 0xd03
+ # CPU revision : 4
+
+ ret, cpuinfo, _ = self._ce.CrosRunCommandWOutput(
+ 'cat /proc/cpuinfo', machine=machine_name, chromeos_root=chromeos_root)
+ self.logger.LogFatalIf(ret,
+ 'Setup ARM CPU failed. Could not retrieve cpuinfo.')
+
+ # List of all CPU cores: 0, 1, ..
+ proc_matches = re.findall(r'^processor\s*: (\d+)$', cpuinfo, re.MULTILINE)
+ # List of all corresponding CPU implementers
+ impl_matches = re.findall(r'^CPU implementer\s*: (0x[\da-f]+)$', cpuinfo,
+ re.MULTILINE)
+ # List of all corresponding CPU part numbers
+ part_matches = re.findall(r'^CPU part\s*: (0x[\da-f]+)$', cpuinfo,
+ re.MULTILINE)
+ assert len(proc_matches) == len(impl_matches)
+ assert len(part_matches) == len(impl_matches)
+
+ all_cores = set(proc_matches)
+ dut_big_cores = {
+ core
+ for core, impl, part in zip(proc_matches, impl_matches, part_matches)
+ if impl in BIG_CORES and part in BIG_CORES[impl]
+ }
+ dut_lit_cores = {
+ core
+ for core, impl, part in zip(proc_matches, impl_matches, part_matches)
+ if impl in LITTLE_CORES and part in LITTLE_CORES[impl]
+ }
+
+ if self.dut_config['cpu_usage'] == 'big_only':
+ cores_to_enable = dut_big_cores
+ cores_to_disable = all_cores - dut_big_cores
+ elif self.dut_config['cpu_usage'] == 'little_only':
+ cores_to_enable = dut_lit_cores
+ cores_to_disable = all_cores - dut_lit_cores
+ else:
+ self.logger.LogError(
+ 'cpu_usage=%s is not supported on ARM.\n'
+ 'Ignore ARM CPU setup and continue.' % self.dut_config['cpu_usage'])
+ return
+
+ if cores_to_enable:
+ cmd_enable_cores = ('echo 1 | tee /sys/devices/system/cpu/cpu{%s}/online'
+ % ','.join(sorted(cores_to_enable)))
+
+ cmd_disable_cores = ''
+ if cores_to_disable:
+ cmd_disable_cores = (
+ 'echo 0 | tee /sys/devices/system/cpu/cpu{%s}/online' % ','.join(
+ sorted(cores_to_disable)))
+
+ ret = self._ce.CrosRunCommand(
+ '; '.join([cmd_enable_cores, cmd_disable_cores]),
+ machine=machine_name,
+ chromeos_root=chromeos_root)
+ self.logger.LogFatalIf(
+ ret, 'Setup ARM CPU failed. Could not retrieve cpuinfo.')
+ else:
+ # If there are no cores enabled by dut_config then configuration
+ # is invalid for current platform and should be ignored.
+ self.logger.LogError(
+ '"cpu_usage" is invalid for targeted platform.\n'
+ 'dut_config[cpu_usage]=%s\n'
+ 'dut big cores: %s\n'
+ 'dut little cores: %s\n'
+ 'Ignore ARM CPU setup and continue.' % (self.dut_config['cpu_usage'],
+ dut_big_cores, dut_lit_cores))
+
def DecreaseWaitTime(self, machine_name, chromeos_root):
"""Change the ten seconds wait time for pagecycler to two seconds."""
FILE = '/usr/local/telemetry/src/tools/perf/page_sets/page_cycler_story.py'
diff --git a/crosperf/suite_runner_unittest.py b/crosperf/suite_runner_unittest.py
index 4af6f4e9..c5a4c181 100755
--- a/crosperf/suite_runner_unittest.py
+++ b/crosperf/suite_runner_unittest.py
@@ -12,8 +12,8 @@ from __future__ import print_function
import os.path
import time
-import mock
import unittest
+import mock
import suite_runner
import label
@@ -23,6 +23,80 @@ from benchmark import Benchmark
from cros_utils import command_executer
from cros_utils import logger
+BIG_LITTLE_CPUINFO = """processor : 0
+model name : ARMv8 Processor rev 4 (v8l)
+BogoMIPS : 48.00
+Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4
+CPU implementer : 0x41
+CPU architecture: 8
+CPU variant : 0x0
+CPU part : 0xd03
+CPU revision : 4
+
+processor : 1
+model name : ARMv8 Processor rev 4 (v8l)
+BogoMIPS : 48.00
+Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4
+CPU implementer : 0x41
+CPU architecture: 8
+CPU variant : 0x0
+CPU part : 0xd03
+CPU revision : 4
+
+processor : 2
+model name : ARMv8 Processor rev 2 (v8l)
+BogoMIPS : 48.00
+Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4
+CPU implementer : 0x41
+CPU architecture: 8
+CPU variant : 0x0
+CPU part : 0xd08
+CPU revision : 2
+"""
+LITTLE_ONLY_CPUINFO = """processor : 0
+model name : ARMv8 Processor rev 4 (v8l)
+BogoMIPS : 48.00
+Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4
+CPU implementer : 0x41
+CPU architecture: 8
+CPU variant : 0x0
+CPU part : 0xd03
+CPU revision : 4
+
+processor : 1
+model name : ARMv8 Processor rev 4 (v8l)
+BogoMIPS : 48.00
+Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4
+CPU implementer : 0x41
+CPU architecture: 8
+CPU variant : 0x0
+CPU part : 0xd03
+CPU revision : 4
+"""
+
+NOT_BIG_LITTLE_CPUINFO = """processor : 0
+model name : ARMv7 Processor rev 1 (v7l)
+Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpv4
+CPU implementer : 0x41
+CPU architecture: 7
+CPU variant : 0x0
+CPU part : 0xc0d
+CPU revision : 1
+
+processor : 1
+model name : ARMv7 Processor rev 1 (v7l)
+Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpv4
+CPU implementer : 0x41
+CPU architecture: 7
+CPU variant : 0x0
+CPU part : 0xc0d
+CPU revision : 1
+
+Hardware : Rockchip (Device Tree)
+Revision : 0000
+Serial : 0000000000000000
+"""
+
class SuiteRunnerTest(unittest.TestCase):
"""Class of SuiteRunner test."""
@@ -68,6 +142,7 @@ class SuiteRunnerTest(unittest.TestCase):
self.call_test_that_run = False
self.disable_aslr_args = []
self.pin_governor_args = []
+ self.setup_cpu_usage_args = []
self.skylab_run_args = []
self.test_that_args = []
self.telemetry_run_args = []
@@ -76,6 +151,7 @@ class SuiteRunnerTest(unittest.TestCase):
self.call_telemetry_crosperf_run = False
self.call_disable_aslr = False
self.call_pin_governor = False
+ self.call_setup_cpu_usage = False
def setUp(self):
self.runner = suite_runner.SuiteRunner(
@@ -93,10 +169,12 @@ class SuiteRunnerTest(unittest.TestCase):
def reset():
self.call_pin_governor = False
+ self.call_setup_cpu_usage = False
self.call_test_that_run = False
self.call_skylab_run = False
self.call_telemetry_crosperf_run = False
self.pin_governor_args = []
+ self.setup_cpu_usage_args = []
self.skylab_run_args = []
self.test_that_args = []
self.telemetry_run_args = []
@@ -110,6 +188,10 @@ class SuiteRunnerTest(unittest.TestCase):
self.call_pin_governor = True
self.pin_governor_args = [machine, chroot]
+ def FakeSetupCpuUsage(machine, chroot):
+ self.call_setup_cpu_usage = True
+ self.setup_cpu_usage_args = [machine, chroot]
+
def FakeSkylabRun(test_label, benchmark, test_args, profiler_args):
self.skylab_run_args = [test_label, benchmark, test_args, profiler_args]
self.call_skylab_run = True
@@ -133,6 +215,7 @@ class SuiteRunnerTest(unittest.TestCase):
self.runner.DisableASLR = FakeDisableASLR
self.runner.PinGovernorExecutionFrequencies = FakePinGovernor
+ self.runner.SetupCpuUsage = FakeSetupCpuUsage
self.runner.Skylab_Run = FakeSkylabRun
self.runner.Telemetry_Crosperf_Run = FakeTelemetryCrosperfRun
self.runner.Test_That_Run = FakeTestThatRun
@@ -146,6 +229,7 @@ class SuiteRunnerTest(unittest.TestCase):
profiler_args)
self.assertFalse(self.call_disable_aslr)
self.assertFalse(self.call_pin_governor)
+ self.assertFalse(self.call_setup_cpu_usage)
self.assertTrue(self.call_skylab_run)
self.assertFalse(self.call_test_that_run)
self.assertFalse(self.call_telemetry_crosperf_run)
@@ -158,6 +242,9 @@ class SuiteRunnerTest(unittest.TestCase):
profiler_args)
self.assertTrue(self.call_disable_aslr)
self.assertTrue(self.call_pin_governor)
+ self.assertTrue(self.call_setup_cpu_usage)
+ self.assertEqual(self.setup_cpu_usage_args,
+ [machine, self.mock_label.chromeos_root])
self.assertTrue(self.call_test_that_run)
self.assertFalse(self.call_telemetry_crosperf_run)
self.assertEqual(
@@ -169,6 +256,7 @@ class SuiteRunnerTest(unittest.TestCase):
test_args, profiler_args)
self.assertTrue(self.call_disable_aslr)
self.assertTrue(self.call_pin_governor)
+ self.assertTrue(self.call_setup_cpu_usage)
self.assertFalse(self.call_test_that_run)
self.assertTrue(self.call_telemetry_crosperf_run)
self.assertEqual(self.telemetry_crosperf_args, [
@@ -217,6 +305,105 @@ class SuiteRunnerTest(unittest.TestCase):
# pyformat: enable
self.assertEqual(cmd, (set_cpu_cmd,))
+ @mock.patch.object(suite_runner.SuiteRunner, 'SetupArmCores')
+ @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommandWOutput')
+ def test_setup_cpu_usage_little_on_arm(self, mock_cros_runcmd_wout,
+ mock_setup_arm):
+ self.mock_cmd_exec.CrosRunCommandWOutput = mock_cros_runcmd_wout
+ self.runner.SetupArmCores = mock_setup_arm
+ mock_cros_runcmd_wout.return_value = (0, 'armv7l', '')
+ self.runner.dut_config['cpu_usage'] = 'little_only'
+ self.runner.SetupCpuUsage('remote.cros', '/tmp/chromeos')
+ self.assertEqual(mock_setup_arm.call_count, 1)
+
+ @mock.patch.object(suite_runner.SuiteRunner, 'SetupArmCores')
+ @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommandWOutput')
+ def test_setup_cpu_usage_big_on_aarch64(self, mock_cros_runcmd_wout,
+ mock_setup_arm):
+ self.mock_cmd_exec.CrosRunCommandWOutput = mock_cros_runcmd_wout
+ self.runner.SetupArmCores = mock_setup_arm
+ mock_cros_runcmd_wout.return_value = (0, 'aarch64', '')
+ self.runner.dut_config['cpu_usage'] = 'big_only'
+ self.runner.SetupCpuUsage('remote.cros', '/tmp/chromeos')
+ self.assertEqual(mock_setup_arm.call_count, 1)
+
+ @mock.patch.object(suite_runner.SuiteRunner, 'SetupArmCores')
+ @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommandWOutput')
+ def test_setup_cpu_usage_all_on_intel(self, mock_cros_runcmd_wout,
+ mock_setup_arm):
+ self.mock_cmd_exec.CrosRunCommandWOutput = mock_cros_runcmd_wout
+ self.runner.SetupArmCores = mock_setup_arm
+ mock_cros_runcmd_wout.return_value = (0, 'x86_64', '')
+ self.runner.dut_config['cpu_usage'] = 'all'
+ self.runner.SetupCpuUsage('remote.cros', '/tmp/chromeos')
+ # Check that SetupArmCores not called.
+ self.assertEqual(mock_setup_arm.call_count, 0)
+
+ @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommandWOutput')
+ @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand')
+ def test_setup_arm_cores_big_on_big_little(self, mock_cros_runcmd,
+ mock_cros_runcmd_wout):
+ self.mock_cmd_exec.CrosRunCommand = mock_cros_runcmd
+ self.mock_cmd_exec.CrosRunCommandWOutput = mock_cros_runcmd_wout
+ mock_cros_runcmd_wout.return_value = (0, BIG_LITTLE_CPUINFO, '')
+ self.runner.dut_config['cpu_usage'] = 'big_only'
+ self.runner.SetupArmCores('remote.cros', '/tmp/chromeos')
+ self.assertEqual(mock_cros_runcmd.call_args_list[0][0],
+ ('echo 1 | tee /sys/devices/system/cpu/cpu{2}/online; '
+ 'echo 0 | tee /sys/devices/system/cpu/cpu{0,1}/online',))
+
+ @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommandWOutput')
+ @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand')
+ def test_setup_arm_cores_little_on_big_little(self, mock_cros_runcmd,
+ mock_cros_runcmd_wout):
+ self.mock_cmd_exec.CrosRunCommand = mock_cros_runcmd
+ self.mock_cmd_exec.CrosRunCommandWOutput = mock_cros_runcmd_wout
+ mock_cros_runcmd_wout.return_value = (0, BIG_LITTLE_CPUINFO, '')
+ self.runner.dut_config['cpu_usage'] = 'little_only'
+ self.runner.SetupArmCores('remote.cros', '/tmp/chromeos')
+ self.assertEqual(mock_cros_runcmd.call_args_list[0][0],
+ ('echo 1 | tee /sys/devices/system/cpu/cpu{0,1}/online; '
+ 'echo 0 | tee /sys/devices/system/cpu/cpu{2}/online',))
+
+ @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommandWOutput')
+ @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand')
+ def test_setup_arm_cores_invalid_config(self, mock_cros_runcmd,
+ mock_cros_runcmd_wout):
+ self.mock_cmd_exec.CrosRunCommand = mock_cros_runcmd
+ self.mock_cmd_exec.CrosRunCommandWOutput = mock_cros_runcmd_wout
+ mock_cros_runcmd_wout.return_value = (0, LITTLE_ONLY_CPUINFO, '')
+ self.runner.dut_config['cpu_usage'] = 'big_only'
+ self.runner.SetupArmCores('remote.cros', '/tmp/chromeos')
+ # Check that CrosRun is not called when trying
+ # to use 'big_only' on a platform with all little cores.
+ self.assertEqual(mock_cros_runcmd.call_count, 0)
+
+ @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommandWOutput')
+ @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand')
+ def test_setup_arm_cores_not_big_little(self, mock_cros_runcmd,
+ mock_cros_runcmd_wout):
+ self.mock_cmd_exec.CrosRunCommand = mock_cros_runcmd
+ self.mock_cmd_exec.CrosRunCommandWOutput = mock_cros_runcmd_wout
+ mock_cros_runcmd_wout.return_value = (0, NOT_BIG_LITTLE_CPUINFO, '')
+ self.runner.dut_config['cpu_usage'] = 'big_only'
+ self.runner.SetupArmCores('remote.cros', '/tmp/chromeos')
+ # Check that CrosRun is not called when trying
+ # to use 'big_only' on a platform w/o support of big/little.
+ self.assertEqual(mock_cros_runcmd.call_count, 0)
+
+ @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommandWOutput')
+ @mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand')
+ def test_setup_arm_cores_unsupported_cpu_usage(self, mock_cros_runcmd,
+ mock_cros_runcmd_wout):
+ self.mock_cmd_exec.CrosRunCommand = mock_cros_runcmd
+ self.mock_cmd_exec.CrosRunCommandWOutput = mock_cros_runcmd_wout
+ mock_cros_runcmd_wout.return_value = (0, BIG_LITTLE_CPUINFO, '')
+ self.runner.dut_config['cpu_usage'] = 'exclusive_cores'
+ self.runner.SetupArmCores('remote.cros', '/tmp/chromeos')
+ # Check that CrosRun is not called when trying to use
+ # 'exclusive_cores' on ARM CPU setup.
+ self.assertEqual(mock_cros_runcmd.call_count, 0)
+
@mock.patch.object(command_executer.CommandExecuter, 'CrosRunCommand')
def test_reboot_machine(self, mock_cros_runcmd):