1import time
2#import numpy
3from lldbtest import *
4
5class 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        self.__nums__ = []
53
54    def __init__(self):
55        self.reset()
56
57    def start(self):
58        if self.__start__ is None:
59            self.__start__ = time.time()
60        else:
61            raise Exception("start() already called, did you forget to stop() first?")
62        # Return self to facilitate the context manager __enter__ protocol.
63        return self
64
65    def stop(self):
66        if self.__start__ is not None:
67            self.__stop__ = time.time()
68            elapsed = self.__stop__ - self.__start__
69            self.__total_elapsed__ += elapsed
70            self.__laps__ += 1
71            self.__nums__.append(elapsed)
72            self.__start__ = None # Reset __start__ to be None again.
73        else:
74            raise Exception("stop() called without first start()?")
75
76    def laps(self):
77        """Gets the number of laps. One lap is equal to a start/stop action."""
78        return self.__laps__
79
80    def avg(self):
81        """Equal to total elapsed time divided by the number of laps."""
82        return self.__total_elapsed__ / self.__laps__
83
84    #def sigma(self):
85    #    """Return the standard deviation of the available samples."""
86    #    if self.__laps__ <= 0:
87    #        return None
88    #    return numpy.std(self.__nums__)
89
90    def __str__(self):
91        return "Avg: %f (Laps: %d, Total Elapsed Time: %f, min=%f, max=%f)" % (self.avg(),
92                                                                               self.__laps__,
93                                                                               self.__total_elapsed__,
94                                                                               min(self.__nums__),
95                                                                               max(self.__nums__))
96
97class BenchBase(TestBase):
98    """
99    Abstract base class for benchmark tests.
100    """
101    def setUp(self):
102        """Fixture for unittest test case setup."""
103        super(BenchBase, self).setUp()
104        #TestBase.setUp(self)
105        self.stopwatch = Stopwatch()
106
107    def tearDown(self):
108        """Fixture for unittest test case teardown."""
109        super(BenchBase, self).tearDown()
110        #TestBase.tearDown(self)
111        del self.stopwatch
112
113