aboutsummaryrefslogtreecommitdiff
path: root/crosperf/benchmark_run.py
diff options
context:
space:
mode:
Diffstat (limited to 'crosperf/benchmark_run.py')
-rw-r--r--crosperf/benchmark_run.py566
1 files changed, 325 insertions, 241 deletions
diff --git a/crosperf/benchmark_run.py b/crosperf/benchmark_run.py
index b5912c11..84797d1c 100644
--- a/crosperf/benchmark_run.py
+++ b/crosperf/benchmark_run.py
@@ -1,10 +1,9 @@
# -*- coding: utf-8 -*-
-# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+# Copyright 2013 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Module of benchmark runs."""
-from __future__ import print_function
import datetime
import threading
@@ -13,254 +12,339 @@ import traceback
from cros_utils import command_executer
from cros_utils import timeline
-
-from suite_runner import SuiteRunner
from results_cache import MockResult
from results_cache import MockResultsCache
from results_cache import Result
from results_cache import ResultsCache
+from suite_runner import SuiteRunner
+
-STATUS_FAILED = 'FAILED'
-STATUS_SUCCEEDED = 'SUCCEEDED'
-STATUS_IMAGING = 'IMAGING'
-STATUS_RUNNING = 'RUNNING'
-STATUS_WAITING = 'WAITING'
-STATUS_PENDING = 'PENDING'
+STATUS_FAILED = "FAILED"
+STATUS_SUCCEEDED = "SUCCEEDED"
+STATUS_IMAGING = "IMAGING"
+STATUS_RUNNING = "RUNNING"
+STATUS_WAITING = "WAITING"
+STATUS_PENDING = "PENDING"
class BenchmarkRun(threading.Thread):
- """The benchmarkrun class."""
-
- def __init__(self, name, benchmark, label, iteration, cache_conditions,
- machine_manager, logger_to_use, log_level, share_cache,
- dut_config):
- threading.Thread.__init__(self)
- self.name = name
- self._logger = logger_to_use
- self.log_level = log_level
- self.benchmark = benchmark
- self.iteration = iteration
- self.label = label
- self.result = None
- self.terminated = False
- self.retval = None
- self.run_completed = False
- self.machine_manager = machine_manager
- self.suite_runner = SuiteRunner(dut_config, self._logger, self.log_level)
- self.machine = None
- self.cache_conditions = cache_conditions
- self.runs_complete = 0
- self.cache_hit = False
- self.failure_reason = ''
- self.test_args = benchmark.test_args
- self.cache = None
- self.profiler_args = self.GetExtraAutotestArgs()
- self._ce = command_executer.GetCommandExecuter(
- self._logger, log_level=self.log_level)
- self.timeline = timeline.Timeline()
- self.timeline.Record(STATUS_PENDING)
- self.share_cache = share_cache
- self.cache_has_been_read = False
-
- # This is used by schedv2.
- self.owner_thread = None
-
- def ReadCache(self):
- # Just use the first machine for running the cached version,
- # without locking it.
- self.cache = ResultsCache()
- self.cache.Init(self.label.chromeos_image, self.label.chromeos_root,
- self.benchmark.test_name, self.iteration, self.test_args,
- self.profiler_args, self.machine_manager, self.machine,
- self.label.board, self.cache_conditions, self._logger,
- self.log_level, self.label, self.share_cache,
- self.benchmark.suite, self.benchmark.show_all_results,
- self.benchmark.run_local, self.benchmark.cwp_dso)
-
- self.result = self.cache.ReadResult()
- self.cache_hit = (self.result is not None)
- self.cache_has_been_read = True
-
- def run(self):
- try:
- if not self.cache_has_been_read:
- self.ReadCache()
-
- if self.result:
- self._logger.LogOutput('%s: Cache hit.' % self.name)
- self._logger.LogOutput(self.result.out, print_to_console=False)
- self._logger.LogError(self.result.err, print_to_console=False)
-
- elif self.label.cache_only:
- self._logger.LogOutput('%s: No cache hit.' % self.name)
- output = '%s: No Cache hit.' % self.name
- retval = 1
- err = 'No cache hit.'
- self.result = Result.CreateFromRun(
- self._logger, self.log_level, self.label, self.machine, output, err,
- retval, self.benchmark.test_name, self.benchmark.suite,
- self.benchmark.cwp_dso)
-
- else:
- self._logger.LogOutput('%s: No cache hit.' % self.name)
- self.timeline.Record(STATUS_WAITING)
- # Try to acquire a machine now.
- self.machine = self.AcquireMachine()
- self.cache.machine = self.machine
- self.result = self.RunTest(self.machine)
-
- self.cache.remote = self.machine.name
- self.label.chrome_version = self.machine_manager.GetChromeVersion(
- self.machine)
- self.cache.StoreResult(self.result)
-
- if not self.label.chrome_version:
- if self.machine:
- self.label.chrome_version = self.machine_manager.GetChromeVersion(
- self.machine)
- elif self.result.chrome_version:
- self.label.chrome_version = self.result.chrome_version
-
- if self.terminated:
- return
-
- if not self.result.retval:
- self.timeline.Record(STATUS_SUCCEEDED)
- else:
+ """The benchmarkrun class."""
+
+ def __init__(
+ self,
+ name,
+ benchmark,
+ label,
+ iteration,
+ cache_conditions,
+ machine_manager,
+ logger_to_use,
+ log_level,
+ share_cache,
+ dut_config,
+ ):
+ threading.Thread.__init__(self)
+ self.name = name
+ self._logger = logger_to_use
+ self.log_level = log_level
+ self.benchmark = benchmark
+ self.iteration = iteration
+ self.label = label
+ self.result = None
+ self.terminated = False
+ self.retval = None
+ self.run_completed = False
+ self.machine_manager = machine_manager
+ self.suite_runner = SuiteRunner(
+ dut_config, self._logger, self.log_level
+ )
+ self.machine = None
+ self.cache_conditions = cache_conditions
+ self.runs_complete = 0
+ self.cache_hit = False
+ self.failure_reason = ""
+ self.test_args = benchmark.test_args
+ self.cache = None
+ self.profiler_args = self.GetExtraAutotestArgs()
+ self._ce = command_executer.GetCommandExecuter(
+ self._logger, log_level=self.log_level
+ )
+ self.timeline = timeline.Timeline()
+ self.timeline.Record(STATUS_PENDING)
+ self.share_cache = share_cache
+ self.cache_has_been_read = False
+
+ # This is used by schedv2.
+ self.owner_thread = None
+
+ def ReadCache(self):
+ # Just use the first machine for running the cached version,
+ # without locking it.
+ self.cache = ResultsCache()
+ self.cache.Init(
+ self.label.chromeos_image,
+ self.label.chromeos_root,
+ self.benchmark.test_name,
+ self.iteration,
+ self.test_args,
+ self.profiler_args,
+ self.machine_manager,
+ self.machine,
+ self.label.board,
+ self.cache_conditions,
+ self._logger,
+ self.log_level,
+ self.label,
+ self.share_cache,
+ self.benchmark.suite,
+ self.benchmark.show_all_results,
+ self.benchmark.run_local,
+ self.benchmark.cwp_dso,
+ )
+
+ self.result = self.cache.ReadResult()
+ self.cache_hit = self.result is not None
+ self.cache_has_been_read = True
+
+ def run(self):
+ try:
+ if not self.cache_has_been_read:
+ self.ReadCache()
+
+ if self.result:
+ self._logger.LogOutput("%s: Cache hit." % self.name)
+ self._logger.LogOutput(self.result.out, print_to_console=False)
+ self._logger.LogError(self.result.err, print_to_console=False)
+
+ elif self.label.cache_only:
+ self._logger.LogOutput("%s: No cache hit." % self.name)
+ output = "%s: No Cache hit." % self.name
+ retval = 1
+ err = "No cache hit."
+ self.result = Result.CreateFromRun(
+ self._logger,
+ self.log_level,
+ self.label,
+ self.machine,
+ output,
+ err,
+ retval,
+ self.benchmark.test_name,
+ self.benchmark.suite,
+ self.benchmark.cwp_dso,
+ )
+
+ else:
+ self._logger.LogOutput("%s: No cache hit." % self.name)
+ self.timeline.Record(STATUS_WAITING)
+ # Try to acquire a machine now.
+ self.machine = self.AcquireMachine()
+ self.cache.machine = self.machine
+ self.result = self.RunTest(self.machine)
+
+ self.cache.remote = self.machine.name
+ self.label.chrome_version = (
+ self.machine_manager.GetChromeVersion(self.machine)
+ )
+ self.cache.StoreResult(self.result)
+
+ if not self.label.chrome_version:
+ if self.machine:
+ self.label.chrome_version = (
+ self.machine_manager.GetChromeVersion(self.machine)
+ )
+ elif self.result.chrome_version:
+ self.label.chrome_version = self.result.chrome_version
+
+ if self.terminated:
+ return
+
+ if not self.result.retval:
+ self.timeline.Record(STATUS_SUCCEEDED)
+ else:
+ if self.timeline.GetLastEvent() != STATUS_FAILED:
+ self.failure_reason = (
+ "Return value of test suite was non-zero."
+ )
+ self.timeline.Record(STATUS_FAILED)
+
+ except Exception as e:
+ self._logger.LogError(
+ "Benchmark run: '%s' failed: %s" % (self.name, e)
+ )
+ traceback.print_exc()
+ if self.timeline.GetLastEvent() != STATUS_FAILED:
+ self.timeline.Record(STATUS_FAILED)
+ self.failure_reason = str(e)
+ finally:
+ if self.owner_thread is not None:
+ # In schedv2 mode, we do not lock machine locally. So noop here.
+ pass
+ elif self.machine:
+ if not self.machine.IsReachable():
+ self._logger.LogOutput(
+ "Machine %s is not reachable, removing it."
+ % self.machine.name
+ )
+ self.machine_manager.RemoveMachine(self.machine.name)
+ self._logger.LogOutput(
+ "Releasing machine: %s" % self.machine.name
+ )
+ self.machine_manager.ReleaseMachine(self.machine)
+ self._logger.LogOutput(
+ "Released machine: %s" % self.machine.name
+ )
+
+ def Terminate(self):
+ self.terminated = True
+ self.suite_runner.Terminate()
if self.timeline.GetLastEvent() != STATUS_FAILED:
- self.failure_reason = 'Return value of test suite was non-zero.'
- self.timeline.Record(STATUS_FAILED)
-
- except Exception as e:
- self._logger.LogError("Benchmark run: '%s' failed: %s" % (self.name, e))
- traceback.print_exc()
- if self.timeline.GetLastEvent() != STATUS_FAILED:
- self.timeline.Record(STATUS_FAILED)
- self.failure_reason = str(e)
- finally:
- if self.owner_thread is not None:
- # In schedv2 mode, we do not lock machine locally. So noop here.
- pass
- elif self.machine:
- if not self.machine.IsReachable():
- self._logger.LogOutput(
- 'Machine %s is not reachable, removing it.' % self.machine.name)
- self.machine_manager.RemoveMachine(self.machine.name)
- self._logger.LogOutput('Releasing machine: %s' % self.machine.name)
- self.machine_manager.ReleaseMachine(self.machine)
- self._logger.LogOutput('Released machine: %s' % self.machine.name)
-
- def Terminate(self):
- self.terminated = True
- self.suite_runner.Terminate()
- if self.timeline.GetLastEvent() != STATUS_FAILED:
- self.timeline.Record(STATUS_FAILED)
- self.failure_reason = 'Thread terminated.'
-
- def AcquireMachine(self):
- if self.owner_thread is not None:
- # No need to lock machine locally, DutWorker, which is a thread, is
- # responsible for running br.
- return self.owner_thread.dut()
- while True:
- machine = None
- if self.terminated:
- raise RuntimeError('Thread terminated while trying to acquire machine.')
-
- machine = self.machine_manager.AcquireMachine(self.label)
-
- if machine:
- self._logger.LogOutput(
- '%s: Machine %s acquired at %s' % (self.name, machine.name,
- datetime.datetime.now()))
- break
- time.sleep(10)
- return machine
-
- def GetExtraAutotestArgs(self):
- if (self.benchmark.perf_args and
- self.benchmark.suite != 'telemetry_Crosperf'):
- self._logger.LogError(
- 'Non-telemetry benchmark does not support profiler.')
- self.benchmark.perf_args = ''
-
- if self.benchmark.perf_args:
- perf_args_list = self.benchmark.perf_args.split(' ')
- perf_args_list = [perf_args_list[0]] + ['-a'] + perf_args_list[1:]
- perf_args = ' '.join(perf_args_list)
- if not perf_args_list[0] in ['record', 'stat']:
- raise SyntaxError('perf_args must start with either record or stat')
- extra_test_args = [
- '--profiler=custom_perf',
- ('--profiler_args=\'perf_options="%s"\'' % perf_args)
- ]
- return ' '.join(extra_test_args)
- else:
- return ''
-
- def RunTest(self, machine):
- self.timeline.Record(STATUS_IMAGING)
- if self.owner_thread is not None:
- # In schedv2 mode, do not even call ImageMachine. Machine image is
- # guarenteed.
- pass
- else:
- self.machine_manager.ImageMachine(machine, self.label)
- self.timeline.Record(STATUS_RUNNING)
- retval, out, err = self.suite_runner.Run(
- machine, self.label, self.benchmark, self.test_args, self.profiler_args)
- self.run_completed = True
- return Result.CreateFromRun(self._logger, self.log_level, self.label,
- self.machine, out, err, retval,
- self.benchmark.test_name, self.benchmark.suite,
- self.benchmark.cwp_dso)
-
- def SetCacheConditions(self, cache_conditions):
- self.cache_conditions = cache_conditions
-
- def logger(self):
- """Return the logger, only used by unittest.
-
- Returns:
- self._logger
- """
-
- return self._logger
-
- def __str__(self):
- """For better debugging."""
-
- return 'BenchmarkRun[name="{}"]'.format(self.name)
+ self.timeline.Record(STATUS_FAILED)
+ self.failure_reason = "Thread terminated."
+
+ def AcquireMachine(self):
+ if self.owner_thread is not None:
+ # No need to lock machine locally, DutWorker, which is a thread, is
+ # responsible for running br.
+ return self.owner_thread.dut()
+ while True:
+ machine = None
+ if self.terminated:
+ raise RuntimeError(
+ "Thread terminated while trying to acquire machine."
+ )
+
+ machine = self.machine_manager.AcquireMachine(self.label)
+
+ if machine:
+ self._logger.LogOutput(
+ "%s: Machine %s acquired at %s"
+ % (self.name, machine.name, datetime.datetime.now())
+ )
+ break
+ time.sleep(10)
+ return machine
+
+ def GetExtraAutotestArgs(self):
+ if (
+ self.benchmark.perf_args
+ and self.benchmark.suite != "telemetry_Crosperf"
+ ):
+ self._logger.LogError(
+ "Non-telemetry benchmark does not support profiler."
+ )
+ self.benchmark.perf_args = ""
+
+ if self.benchmark.perf_args:
+ perf_args_list = self.benchmark.perf_args.split(" ")
+ perf_args_list = [perf_args_list[0]] + ["-a"] + perf_args_list[1:]
+ perf_args = " ".join(perf_args_list)
+ if not perf_args_list[0] in ["record", "stat"]:
+ raise SyntaxError(
+ "perf_args must start with either record or stat"
+ )
+ extra_test_args = [
+ "--profiler=custom_perf",
+ ("--profiler_args='perf_options=\"%s\"'" % perf_args),
+ ]
+ return " ".join(extra_test_args)
+ else:
+ return ""
+
+ def RunTest(self, machine):
+ self.timeline.Record(STATUS_IMAGING)
+ if self.owner_thread is not None:
+ # In schedv2 mode, do not even call ImageMachine. Machine image is
+ # guarenteed.
+ pass
+ else:
+ self.machine_manager.ImageMachine(machine, self.label)
+ self.timeline.Record(STATUS_RUNNING)
+ retval, out, err = self.suite_runner.Run(
+ machine,
+ self.label,
+ self.benchmark,
+ self.test_args,
+ self.profiler_args,
+ )
+ self.run_completed = True
+ return Result.CreateFromRun(
+ self._logger,
+ self.log_level,
+ self.label,
+ self.machine,
+ out,
+ err,
+ retval,
+ self.benchmark.test_name,
+ self.benchmark.suite,
+ self.benchmark.cwp_dso,
+ )
+
+ def SetCacheConditions(self, cache_conditions):
+ self.cache_conditions = cache_conditions
+
+ def logger(self):
+ """Return the logger, only used by unittest.
+
+ Returns:
+ self._logger
+ """
+
+ return self._logger
+
+ def __str__(self):
+ """For better debugging."""
+
+ return 'BenchmarkRun[name="{}"]'.format(self.name)
class MockBenchmarkRun(BenchmarkRun):
- """Inherited from BenchmarkRun."""
-
- def ReadCache(self):
- # Just use the first machine for running the cached version,
- # without locking it.
- self.cache = MockResultsCache()
- self.cache.Init(self.label.chromeos_image, self.label.chromeos_root,
- self.benchmark.test_name, self.iteration, self.test_args,
- self.profiler_args, self.machine_manager, self.machine,
- self.label.board, self.cache_conditions, self._logger,
- self.log_level, self.label, self.share_cache,
- self.benchmark.suite, self.benchmark.show_all_results,
- self.benchmark.run_local, self.benchmark.cwp_dso)
-
- self.result = self.cache.ReadResult()
- self.cache_hit = (self.result is not None)
-
- def RunTest(self, machine):
- """Remove Result.CreateFromRun for testing."""
- self.timeline.Record(STATUS_IMAGING)
- self.machine_manager.ImageMachine(machine, self.label)
- self.timeline.Record(STATUS_RUNNING)
- [retval, out, err] = self.suite_runner.Run(
- machine, self.label, self.benchmark, self.test_args, self.profiler_args)
- self.run_completed = True
- rr = MockResult('logger', self.label, self.log_level, machine)
- rr.out = out
- rr.err = err
- rr.retval = retval
- return rr
+ """Inherited from BenchmarkRun."""
+
+ def ReadCache(self):
+ # Just use the first machine for running the cached version,
+ # without locking it.
+ self.cache = MockResultsCache()
+ self.cache.Init(
+ self.label.chromeos_image,
+ self.label.chromeos_root,
+ self.benchmark.test_name,
+ self.iteration,
+ self.test_args,
+ self.profiler_args,
+ self.machine_manager,
+ self.machine,
+ self.label.board,
+ self.cache_conditions,
+ self._logger,
+ self.log_level,
+ self.label,
+ self.share_cache,
+ self.benchmark.suite,
+ self.benchmark.show_all_results,
+ self.benchmark.run_local,
+ self.benchmark.cwp_dso,
+ )
+
+ self.result = self.cache.ReadResult()
+ self.cache_hit = self.result is not None
+
+ def RunTest(self, machine):
+ """Remove Result.CreateFromRun for testing."""
+ self.timeline.Record(STATUS_IMAGING)
+ self.machine_manager.ImageMachine(machine, self.label)
+ self.timeline.Record(STATUS_RUNNING)
+ [retval, out, err] = self.suite_runner.Run(
+ machine,
+ self.label,
+ self.benchmark,
+ self.test_args,
+ self.profiler_args,
+ )
+ self.run_completed = True
+ rr = MockResult("logger", self.label, self.log_level, machine)
+ rr.out = out
+ rr.err = err
+ rr.retval = retval
+ return rr