xref: /llvm-project/lldb/packages/Python/lldbsuite/test/lldbbench.py (revision e634c2f7149392b62e93c1b2b75701a12bc06721)
1# System modules
2import time
3
4# Third-party modules
5
6# LLDB modules
7from .lldbtest import *
8
9
10class Stopwatch(object):
11    """Stopwatch provides a simple utility to start/stop your stopwatch multiple
12    times.  Each start/stop is equal to a lap, with its elapsed time accumulated
13    while measurement is in progress.
14
15    When you're ready to start from scratch for another round of measurements,
16    be sure to call the reset() method.
17
18    For example,
19
20    sw = Stopwatch()
21    for i in range(1000):
22        with sw:
23            # Do some length operations...
24            ...
25    # Get the average time.
26    avg_time = sw.avg()
27
28    # Reset the stopwatch as we are about to perform other kind of operations.
29    sw.reset()
30    ...
31    """
32
33    #############################################################
34    #
35    # Context manager interfaces to support the 'with' statement.
36    #
37    #############################################################
38
39    def __enter__(self):
40        """
41        Context management protocol on entry to the body of the with statement.
42        """
43        return self.start()
44
45    def __exit__(self, type, value, tb):
46        """
47        Context management protocol on exit from the body of the with statement.
48        """
49        self.stop()
50
51    def reset(self):
52        self.__laps__ = 0
53        self.__total_elapsed__ = 0.0
54        self.__start__ = None
55        self.__stop__ = None
56        self.__elapsed__ = 0.0
57        self.__nums__ = []
58
59    def __init__(self):
60        self.reset()
61
62    def start(self):
63        if self.__start__ is None:
64            self.__start__ = time.time()
65        else:
66            raise Exception("start() already called, did you forget to stop() first?")
67        # Return self to facilitate the context manager __enter__ protocol.
68        return self
69
70    def stop(self):
71        if self.__start__ is not None:
72            self.__stop__ = time.time()
73            elapsed = self.__stop__ - self.__start__
74            self.__total_elapsed__ += elapsed
75            self.__laps__ += 1
76            self.__nums__.append(elapsed)
77            self.__start__ = None  # Reset __start__ to be None again.
78        else:
79            raise Exception("stop() called without first start()?")
80
81    def laps(self):
82        """Gets the number of laps. One lap is equal to a start/stop action."""
83        return self.__laps__
84
85    def avg(self):
86        """Equal to total elapsed time divided by the number of laps."""
87        return self.__total_elapsed__ / self.__laps__
88
89    # def sigma(self):
90    #    """Return the standard deviation of the available samples."""
91    #    if self.__laps__ <= 0:
92    #        return None
93    #    return numpy.std(self.__nums__)
94
95    def __str__(self):
96        return "Avg: %f (Laps: %d, Total Elapsed Time: %f, min=%f, max=%f)" % (
97            self.avg(),
98            self.__laps__,
99            self.__total_elapsed__,
100            min(self.__nums__),
101            max(self.__nums__),
102        )
103
104
105class BenchBase(TestBase):
106    """
107    Abstract base class for benchmark tests.
108    """
109
110    def setUp(self):
111        """Fixture for unittest test case setup."""
112        super(BenchBase, self).setUp()
113        # TestBase.setUp(self)
114        self.stopwatch = Stopwatch()
115
116    def tearDown(self):
117        """Fixture for unittest test case teardown."""
118        super(BenchBase, self).tearDown()
119        # TestBase.tearDown(self)
120        del self.stopwatch
121