Johnny Chen | cbfd093 | 2011-08-02 00:43:09 +0000 | [diff] [blame] | 1 | import time |
Johnny Chen | 71cb797 | 2011-08-01 21:13:26 +0000 | [diff] [blame] | 2 | from lldbtest import benchmarks_test |
Johnny Chen | cbfd093 | 2011-08-02 00:43:09 +0000 | [diff] [blame] | 3 | from lldbtest import Base |
Johnny Chen | 71cb797 | 2011-08-01 21:13:26 +0000 | [diff] [blame] | 4 | |
Johnny Chen | cbfd093 | 2011-08-02 00:43:09 +0000 | [diff] [blame] | 5 | class Stopwatch(object): |
| 6 | """Stopwatch provides a simple utility to start/stop your stopwatch multiple |
| 7 | times. Each start/stop is equal to a lap, with its elapsed time accumulated |
| 8 | while measurment is in progress. |
| 9 | |
| 10 | When you're ready to start from scratch for another round of measurements, |
| 11 | be sure to call the reset() method. |
| 12 | |
| 13 | For example, |
| 14 | |
| 15 | sw = Stopwatch() |
| 16 | for i in range(1000): |
| 17 | with sw: |
| 18 | # Do some length operations... |
| 19 | ... |
| 20 | # Get the average time. |
| 21 | avg_time = sw.avg() |
| 22 | |
| 23 | # Reset the stopwatch as we are about to perform other kind of operations. |
| 24 | sw.reset() |
| 25 | ... |
| 26 | """ |
| 27 | |
| 28 | ############################################################# |
| 29 | # |
| 30 | # Context manager interfaces to support the 'with' statement. |
| 31 | # |
| 32 | ############################################################# |
| 33 | |
| 34 | def __enter__(self): |
| 35 | """ |
| 36 | Context management protocol on entry to the body of the with statement. |
| 37 | """ |
| 38 | return self.start() |
| 39 | |
| 40 | def __exit__(self, type, value, tb): |
| 41 | """ |
| 42 | Context management protocol on exit from the body of the with statement. |
| 43 | """ |
| 44 | self.stop() |
| 45 | |
| 46 | def reset(self): |
| 47 | self.__laps__ = 0 |
| 48 | self.__total_elapsed__ = 0.0 |
| 49 | self.__start__ = None |
| 50 | self.__stop__ = None |
| 51 | self.__elapsed__ = 0.0 |
| 52 | |
| 53 | def __init__(self): |
| 54 | self.reset() |
| 55 | |
| 56 | def start(self): |
| 57 | if self.__start__ is None: |
| 58 | self.__start__ = time.time() |
| 59 | else: |
| 60 | raise Exception("start() already called, did you forget to stop() first?") |
| 61 | # Return self to facilitate the context manager __enter__ protocol. |
| 62 | return self |
| 63 | |
| 64 | def stop(self): |
| 65 | if self.__start__ is not None: |
| 66 | self.__stop__ = time.time() |
| 67 | elapsed = self.__stop__ - self.__start__ |
| 68 | self.__total_elapsed__ += elapsed |
| 69 | self.__laps__ += 1 |
| 70 | self.__start__ = None # Reset __start__ to be None again. |
| 71 | else: |
| 72 | raise Exception("stop() called without first start()?") |
| 73 | |
| 74 | def laps(self): |
| 75 | """Gets the number of laps. One lap is equal to a start/stop action.""" |
| 76 | return self.__laps__ |
| 77 | |
| 78 | def avg(self): |
| 79 | """Equal to total elapsed time divided by the number of laps.""" |
| 80 | return self.__total_elapsed__ / self.__laps__ |
| 81 | |
| 82 | def __str__(self): |
| 83 | return "Avg: %f (Laps: %d, Total Elapsed Time: %d)" % (self.avg(), |
| 84 | self.__laps__, |
| 85 | self.__total_elapsed__) |
| 86 | |
| 87 | class BenchBase(Base): |
Johnny Chen | 71cb797 | 2011-08-01 21:13:26 +0000 | [diff] [blame] | 88 | """ |
| 89 | Abstract base class for benchmark tests. |
| 90 | """ |
Johnny Chen | cbfd093 | 2011-08-02 00:43:09 +0000 | [diff] [blame] | 91 | def setUp(self): |
| 92 | """Fixture for unittest test case setup.""" |
| 93 | Base.setUp(self) |
Johnny Chen | bd43453 | 2011-08-02 00:50:55 +0000 | [diff] [blame^] | 94 | self.stopwatch = Stopwatch() |
Johnny Chen | cbfd093 | 2011-08-02 00:43:09 +0000 | [diff] [blame] | 95 | |
| 96 | def tearDown(self): |
| 97 | """Fixture for unittest test case teardown.""" |
| 98 | Base.tearDown(self) |
Johnny Chen | bd43453 | 2011-08-02 00:50:55 +0000 | [diff] [blame^] | 99 | del self.stopwatch |
Johnny Chen | 71cb797 | 2011-08-01 21:13:26 +0000 | [diff] [blame] | 100 | |