Home | History | Annotate | Download | only in skpbench
      1 # Copyright 2016 Google Inc.
      2 #
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 import time
      7 
      8 class Hardware:
      9   """Locks down and monitors hardware for benchmarking.
     10 
     11   This is a common base for classes that can control the specific hardware
     12   we are running on. Its purpose is to lock the hardware into a constant
     13   benchmarking mode for the duration of a 'with' block. e.g.:
     14 
     15     with hardware:
     16       run_benchmark()
     17 
     18   While benchmarking, the caller must call sanity_check() frequently to verify
     19   the hardware state has not changed.
     20 
     21   """
     22 
     23   def __init__(self):
     24     self.warmup_time = 0
     25 
     26   def __enter__(self):
     27     return self
     28 
     29   def __exit__(self, exception_type, exception_value, traceback):
     30     pass
     31 
     32   def filter_line(self, line):
     33     """Returns False if the provided output line can be suppressed."""
     34     return True
     35 
     36   def sanity_check(self):
     37     """Raises a HardwareException if any hardware state is not as expected."""
     38     pass
     39 
     40   def print_debug_diagnostics(self):
     41     """Prints any info that may help improve or debug hardware monitoring."""
     42     pass
     43 
     44 
     45 class HardwareException(Exception):
     46   """Gets thrown when certain hardware state is not what we expect.
     47 
     48   Generally this happens because of thermal conditions or other variables beyond
     49   our control, and the appropriate course of action is to take a short nap
     50   before resuming the benchmark.
     51 
     52   """
     53 
     54   def __init__(self, message, sleeptime=60):
     55     Exception.__init__(self, message)
     56     self.sleeptime = sleeptime
     57 
     58 
     59 class Expectation:
     60   """Simple helper for checking the readings on hardware gauges."""
     61   def __init__(self, value_type, min_value=None, max_value=None,
     62                exact_value=None, name=None, sleeptime=60):
     63     self.value_type = value_type
     64     self.min_value = min_value
     65     self.max_value = max_value
     66     self.exact_value = exact_value
     67     self.name = name
     68     self.sleeptime = sleeptime
     69 
     70   def check(self, stringvalue):
     71     typedvalue = self.value_type(stringvalue)
     72     if self.min_value is not None and typedvalue < self.min_value:
     73        raise HardwareException("%s is too low (%s, min=%s)" %
     74                                (self.name, stringvalue, str(self.min_value)),
     75                                sleeptime=self.sleeptime)
     76     if self.max_value is not None and typedvalue > self.max_value:
     77        raise HardwareException("%s is too high (%s, max=%s)" %
     78                                (self.name, stringvalue, str(self.max_value)),
     79                                sleeptime=self.sleeptime)
     80     if self.exact_value is not None and typedvalue != self.exact_value:
     81        raise HardwareException("unexpected %s (%s, expected=%s)" %
     82                                (self.name, stringvalue, str(self.exact_value)),
     83                                sleeptime=self.sleeptime)
     84 
     85   @staticmethod
     86   def check_all(expectations, stringvalues):
     87     if len(stringvalues) != len(expectations):
     88       raise Exception("unexpected reading from hardware gauges "
     89                       "(expected %i values):\n%s" %
     90                       (len(expectations), '\n'.join(stringvalues)))
     91 
     92     for value, expected in zip(stringvalues, expectations):
     93       expected.check(value)
     94