Profiler class. self.cur is always a tuple. Each such tuple corresponds to a stack frame that is currently active (self.cur[-2]). The following are the definitions of its members. We use this external "parallel stack" to avoid contaminating the program that we are profiling. (old
| 110 | |
| 111 | |
| 112 | class Profile: |
| 113 | """Profiler class. |
| 114 | |
| 115 | self.cur is always a tuple. Each such tuple corresponds to a stack |
| 116 | frame that is currently active (self.cur[-2]). The following are the |
| 117 | definitions of its members. We use this external "parallel stack" to |
| 118 | avoid contaminating the program that we are profiling. (old profiler |
| 119 | used to write into the frames local dictionary!!) Derived classes |
| 120 | can change the definition of some entries, as long as they leave |
| 121 | [-2:] intact (frame and previous tuple). In case an internal error is |
| 122 | detected, the -3 element is used as the function name. |
| 123 | |
| 124 | [ 0] = Time that needs to be charged to the parent frame's function. |
| 125 | It is used so that a function call will not have to access the |
| 126 | timing data for the parent frame. |
| 127 | [ 1] = Total time spent in this frame's function, excluding time in |
| 128 | subfunctions (this latter is tallied in cur[2]). |
| 129 | [ 2] = Total time spent in subfunctions, excluding time executing the |
| 130 | frame's function (this latter is tallied in cur[1]). |
| 131 | [-3] = Name of the function that corresponds to this frame. |
| 132 | [-2] = Actual frame that we correspond to (used to sync exception handling). |
| 133 | [-1] = Our parent 6-tuple (corresponds to frame.f_back). |
| 134 | |
| 135 | Timing data for each function is stored as a 5-tuple in the dictionary |
| 136 | self.timings[]. The index is always the name stored in self.cur[-3]. |
| 137 | The following are the definitions of the members: |
| 138 | |
| 139 | [0] = The number of times this function was called, not counting direct |
| 140 | or indirect recursion, |
| 141 | [1] = Number of times this function appears on the stack, minus one |
| 142 | [2] = Total time spent internal to this function |
| 143 | [3] = Cumulative time that this function was present on the stack. In |
| 144 | non-recursive functions, this is the total execution time from start |
| 145 | to finish of each invocation of a function, including time spent in |
| 146 | all subfunctions. |
| 147 | [4] = A dictionary indicating for each function name, the number of times |
| 148 | it was called by us. |
| 149 | """ |
| 150 | |
| 151 | bias = 0 # calibration constant |
| 152 | |
| 153 | def __init__(self, timer=None, bias=None): |
| 154 | self.timings = {} |
| 155 | self.cur = None |
| 156 | self.cmd = "" |
| 157 | self.c_func_name = "" |
| 158 | |
| 159 | if bias is None: |
| 160 | bias = self.bias |
| 161 | self.bias = bias # Materialize in local dict for lookup speed. |
| 162 | |
| 163 | if not timer: |
| 164 | self.timer = self.get_time = time.process_time |
| 165 | self.dispatcher = self.trace_dispatch_i |
| 166 | else: |
| 167 | self.timer = timer |
| 168 | t = self.timer() # test out timer function |
| 169 | try: |
no outgoing calls
no test coverage detected
searching dependent graphs…