Back to index

python3.2  3.2.2
Classes | Public Member Functions | Public Attributes | Static Public Attributes | Private Member Functions
profile.Profile Class Reference

List of all members.

Classes

class  fake_code
class  fake_frame

Public Member Functions

def __init__
def trace_dispatch
def trace_dispatch_i
def trace_dispatch_mac
def trace_dispatch_l
def trace_dispatch_exception
def trace_dispatch_call
def trace_dispatch_c_call
def trace_dispatch_return
def set_cmd
def simulate_call
def simulate_cmd_complete
def print_stats
def dump_stats
def create_stats
def snapshot_stats
def run
def runctx
def runcall
def calibrate

Public Attributes

 timings
 cur
 cmd
 c_func_name
 bias
 timer
 dispatcher
 get_time
 t
 stats

Static Public Attributes

int bias = 0
dictionary dispatch

Private Member Functions

def _calibrate_inner

Detailed Description

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 profiler
used to write into the frames local dictionary!!) Derived classes
can change the definition of some entries, as long as they leave
[-2:] intact (frame and previous tuple).  In case an internal error is
detected, the -3 element is used as the function name.

[ 0] = Time that needs to be charged to the parent frame's function.
       It is used so that a function call will not have to access the
       timing data for the parent frame.
[ 1] = Total time spent in this frame's function, excluding time in
       subfunctions (this latter is tallied in cur[2]).
[ 2] = Total time spent in subfunctions, excluding time executing the
       frame's function (this latter is tallied in cur[1]).
[-3] = Name of the function that corresponds to this frame.
[-2] = Actual frame that we correspond to (used to sync exception handling).
[-1] = Our parent 6-tuple (corresponds to frame.f_back).

Timing data for each function is stored as a 5-tuple in the dictionary
self.timings[].  The index is always the name stored in self.cur[-3].
The following are the definitions of the members:

[0] = The number of times this function was called, not counting direct
      or indirect recursion,
[1] = Number of times this function appears on the stack, minus one
[2] = Total time spent internal to this function
[3] = Cumulative time that this function was present on the stack.  In
      non-recursive functions, this is the total execution time from start
      to finish of each invocation of a function, including time spent in
      all subfunctions.
[4] = A dictionary indicating for each function name, the number of times
      it was called by us.

Definition at line 106 of file profile.py.


Constructor & Destructor Documentation

def profile.Profile.__init__ (   self,
  timer = None,
  bias = None 
)

Definition at line 147 of file profile.py.

00147 
00148     def __init__(self, timer=None, bias=None):
00149         self.timings = {}
00150         self.cur = None
00151         self.cmd = ""
00152         self.c_func_name = ""
00153 
00154         if bias is None:
00155             bias = self.bias
00156         self.bias = bias     # Materialize in local dict for lookup speed.
00157 
00158         if not timer:
00159             if _has_res:
00160                 self.timer = resgetrusage
00161                 self.dispatcher = self.trace_dispatch
00162                 self.get_time = _get_time_resource
00163             elif hasattr(time, 'clock'):
00164                 self.timer = self.get_time = time.clock
00165                 self.dispatcher = self.trace_dispatch_i
00166             elif hasattr(os, 'times'):
00167                 self.timer = os.times
00168                 self.dispatcher = self.trace_dispatch
00169                 self.get_time = _get_time_times
00170             else:
00171                 self.timer = self.get_time = time.time
00172                 self.dispatcher = self.trace_dispatch_i
00173         else:
00174             self.timer = timer
00175             t = self.timer() # test out timer function
00176             try:
00177                 length = len(t)
00178             except TypeError:
00179                 self.get_time = timer
00180                 self.dispatcher = self.trace_dispatch_i
00181             else:
00182                 if length == 2:
00183                     self.dispatcher = self.trace_dispatch
00184                 else:
00185                     self.dispatcher = self.trace_dispatch_l
00186                 # This get_time() implementation needs to be defined
00187                 # here to capture the passed-in timer in the parameter
00188                 # list (for performance).  Note that we can't assume
00189                 # the timer() result contains two values in all
00190                 # cases.
00191                 def get_time_timer(timer=timer, sum=sum):
00192                     return sum(timer())
00193                 self.get_time = get_time_timer
00194         self.t = self.get_time()
00195         self.simulate_call('profiler')

Here is the caller graph for this function:


Member Function Documentation

def profile.Profile._calibrate_inner (   self,
  m,
  verbose 
) [private]

Definition at line 505 of file profile.py.

00505 
00506     def _calibrate_inner(self, m, verbose):
00507         get_time = self.get_time
00508 
00509         # Set up a test case to be run with and without profiling.  Include
00510         # lots of calls, because we're trying to quantify stopwatch overhead.
00511         # Do not raise any exceptions, though, because we want to know
00512         # exactly how many profile events are generated (one call event, +
00513         # one return event, per Python-level call).
00514 
00515         def f1(n):
00516             for i in range(n):
00517                 x = 1
00518 
00519         def f(m, f1=f1):
00520             for i in range(m):
00521                 f1(100)
00522 
00523         f(m)    # warm up the cache
00524 
00525         # elapsed_noprofile <- time f(m) takes without profiling.
00526         t0 = get_time()
00527         f(m)
00528         t1 = get_time()
00529         elapsed_noprofile = t1 - t0
00530         if verbose:
00531             print("elapsed time without profiling =", elapsed_noprofile)
00532 
00533         # elapsed_profile <- time f(m) takes with profiling.  The difference
00534         # is profiling overhead, only some of which the profiler subtracts
00535         # out on its own.
00536         p = Profile()
00537         t0 = get_time()
00538         p.runctx('f(m)', globals(), locals())
00539         t1 = get_time()
00540         elapsed_profile = t1 - t0
00541         if verbose:
00542             print("elapsed time with profiling =", elapsed_profile)
00543 
00544         # reported_time <- "CPU seconds" the profiler charged to f and f1.
00545         total_calls = 0.0
00546         reported_time = 0.0
00547         for (filename, line, funcname), (cc, ns, tt, ct, callers) in \
00548                 p.timings.items():
00549             if funcname in ("f", "f1"):
00550                 total_calls += cc
00551                 reported_time += tt
00552 
00553         if verbose:
00554             print("'CPU seconds' profiler reported =", reported_time)
00555             print("total # calls =", total_calls)
00556         if total_calls != m + 1:
00557             raise ValueError("internal error: total calls = %d" % total_calls)
00558 
00559         # reported_time - elapsed_noprofile = overhead the profiler wasn't
00560         # able to measure.  Divide by twice the number of calls (since there
00561         # are two profiler events per call in this test) to get the hidden
00562         # overhead per event.
00563         mean = (reported_time - elapsed_noprofile) / 2.0 / total_calls
00564         if verbose:
00565             print("mean stopwatch overhead per profile event =", mean)
00566         return mean
00567 
00568 #****************************************************************************

Here is the caller graph for this function:

def profile.Profile.calibrate (   self,
  m,
  verbose = 0 
)

Definition at line 494 of file profile.py.

00494 
00495     def calibrate(self, m, verbose=0):
00496         if self.__class__ is not Profile:
00497             raise TypeError("Subclasses must override .calibrate().")
00498 
00499         saved_bias = self.bias
00500         self.bias = 0
00501         try:
00502             return self._calibrate_inner(m, verbose)
00503         finally:
00504             self.bias = saved_bias

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 413 of file profile.py.

00413 
00414     def create_stats(self):
00415         self.simulate_cmd_complete()
00416         self.snapshot_stats()

Here is the call graph for this function:

Here is the caller graph for this function:

def profile.Profile.dump_stats (   self,
  file 
)

Definition at line 407 of file profile.py.

00407 
00408     def dump_stats(self, file):
00409         f = open(file, 'wb')
00410         self.create_stats()
00411         marshal.dump(self.stats, f)
00412         f.close()

Here is the call graph for this function:

def profile.Profile.print_stats (   self,
  sort = -1 
)

Definition at line 402 of file profile.py.

00402 
00403     def print_stats(self, sort=-1):
00404         import pstats
00405         pstats.Stats(self).strip_dirs().sort_stats(sort). \
00406                   print_stats()

def profile.Profile.run (   self,
  cmd 
)

Definition at line 430 of file profile.py.

00430 
00431     def run(self, cmd):
00432         import __main__
00433         dict = __main__.__dict__
00434         return self.runctx(cmd, dict, dict)

Here is the call graph for this function:

Here is the caller graph for this function:

def profile.Profile.runcall (   self,
  func,
  args,
  kw 
)

Definition at line 445 of file profile.py.

00445 
00446     def runcall(self, func, *args, **kw):
00447         self.set_cmd(repr(func))
00448         sys.setprofile(self.dispatcher)
00449         try:
00450             return func(*args, **kw)
00451         finally:
00452             sys.setprofile(None)
00453 

Here is the call graph for this function:

def profile.Profile.runctx (   self,
  cmd,
  globals,
  locals 
)

Definition at line 435 of file profile.py.

00435 
00436     def runctx(self, cmd, globals, locals):
00437         self.set_cmd(cmd)
00438         sys.setprofile(self.dispatcher)
00439         try:
00440             exec(cmd, globals, locals)
00441         finally:
00442             sys.setprofile(None)
00443         return self

Here is the call graph for this function:

Here is the caller graph for this function:

def profile.Profile.set_cmd (   self,
  cmd 
)

Definition at line 359 of file profile.py.

00359 
00360     def set_cmd(self, cmd):
00361         if self.cur[-1]: return   # already set
00362         self.cmd = cmd
00363         self.simulate_call(cmd)

Here is the call graph for this function:

Here is the caller graph for this function:

def profile.Profile.simulate_call (   self,
  name 
)

Definition at line 379 of file profile.py.

00379 
00380     def simulate_call(self, name):
00381         code = self.fake_code('profile', 0, name)
00382         if self.cur:
00383             pframe = self.cur[-2]
00384         else:
00385             pframe = None
00386         frame = self.fake_frame(code, pframe)
00387         self.dispatch['call'](self, frame, 0)

Here is the caller graph for this function:

Definition at line 391 of file profile.py.

00391 
00392     def simulate_cmd_complete(self):
00393         get_time = self.get_time
00394         t = get_time() - self.t
00395         while self.cur[-1]:
00396             # We *can* cause assertion errors here if
00397             # dispatch_trace_return checks for a frame match!
00398             self.dispatch['return'](self, self.cur[-2], t)
00399             t = 0
00400         self.t = get_time() - t
00401 

Here is the caller graph for this function:

Definition at line 417 of file profile.py.

00417 
00418     def snapshot_stats(self):
00419         self.stats = {}
00420         for func, (cc, ns, tt, ct, callers) in self.timings.items():
00421             callers = callers.copy()
00422             nc = 0
00423             for callcnt in callers.values():
00424                 nc += callcnt
00425             self.stats[func] = cc, nc, tt, ct, callers
00426 

Here is the caller graph for this function:

def profile.Profile.trace_dispatch (   self,
  frame,
  event,
  arg 
)

Definition at line 198 of file profile.py.

00198 
00199     def trace_dispatch(self, frame, event, arg):
00200         timer = self.timer
00201         t = timer()
00202         t = t[0] + t[1] - self.t - self.bias
00203 
00204         if event == "c_call":
00205             self.c_func_name = arg.__name__
00206 
00207         if self.dispatch[event](self, frame,t):
00208             t = timer()
00209             self.t = t[0] + t[1]
00210         else:
00211             r = timer()
00212             self.t = r[0] + r[1] - t # put back unrecorded delta

def profile.Profile.trace_dispatch_c_call (   self,
  frame,
  t 
)

Definition at line 294 of file profile.py.

00294 
00295     def trace_dispatch_c_call (self, frame, t):
00296         fn = ("", 0, self.c_func_name)
00297         self.cur = (t, 0, 0, fn, frame, self.cur)
00298         timings = self.timings
00299         if fn in timings:
00300             cc, ns, tt, ct, callers = timings[fn]
00301             timings[fn] = cc, ns+1, tt, ct, callers
00302         else:
00303             timings[fn] = 0, 0, 0, 0, {}
00304         return 1

def profile.Profile.trace_dispatch_call (   self,
  frame,
  t 
)

Definition at line 272 of file profile.py.

00272 
00273     def trace_dispatch_call(self, frame, t):
00274         if self.cur and frame.f_back is not self.cur[-2]:
00275             rpt, rit, ret, rfn, rframe, rcur = self.cur
00276             if not isinstance(rframe, Profile.fake_frame):
00277                 assert rframe.f_back is frame.f_back, ("Bad call", rfn,
00278                                                        rframe, rframe.f_back,
00279                                                        frame, frame.f_back)
00280                 self.trace_dispatch_return(rframe, 0)
00281                 assert (self.cur is None or \
00282                         frame.f_back is self.cur[-2]), ("Bad call",
00283                                                         self.cur[-3])
00284         fcode = frame.f_code
00285         fn = (fcode.co_filename, fcode.co_firstlineno, fcode.co_name)
00286         self.cur = (t, 0, 0, fn, frame, self.cur)
00287         timings = self.timings
00288         if fn in timings:
00289             cc, ns, tt, ct, callers = timings[fn]
00290             timings[fn] = cc, ns + 1, tt, ct, callers
00291         else:
00292             timings[fn] = 0, 0, 0, 0, {}
00293         return 1

Here is the call graph for this function:

def profile.Profile.trace_dispatch_exception (   self,
  frame,
  t 
)

Definition at line 264 of file profile.py.

00264 
00265     def trace_dispatch_exception(self, frame, t):
00266         rpt, rit, ret, rfn, rframe, rcur = self.cur
00267         if (rframe is not frame) and rcur:
00268             return self.trace_dispatch_return(rframe, t)
00269         self.cur = rpt, rit+t, ret, rfn, rframe, rcur
00270         return 1
00271 

Here is the call graph for this function:

def profile.Profile.trace_dispatch_i (   self,
  frame,
  event,
  arg 
)

Definition at line 216 of file profile.py.

00216 
00217     def trace_dispatch_i(self, frame, event, arg):
00218         timer = self.timer
00219         t = timer() - self.t - self.bias
00220 
00221         if event == "c_call":
00222             self.c_func_name = arg.__name__
00223 
00224         if self.dispatch[event](self, frame, t):
00225             self.t = timer()
00226         else:
00227             self.t = timer() - t  # put back unrecorded delta

def profile.Profile.trace_dispatch_l (   self,
  frame,
  event,
  arg 
)

Definition at line 245 of file profile.py.

00245 
00246     def trace_dispatch_l(self, frame, event, arg):
00247         get_time = self.get_time
00248         t = get_time() - self.t - self.bias
00249 
00250         if event == "c_call":
00251             self.c_func_name = arg.__name__
00252 
00253         if self.dispatch[event](self, frame, t):
00254             self.t = get_time()
00255         else:
00256             self.t = get_time() - t # put back unrecorded delta

def profile.Profile.trace_dispatch_mac (   self,
  frame,
  event,
  arg 
)

Definition at line 231 of file profile.py.

00231 
00232     def trace_dispatch_mac(self, frame, event, arg):
00233         timer = self.timer
00234         t = timer()/60.0 - self.t - self.bias
00235 
00236         if event == "c_call":
00237             self.c_func_name = arg.__name__
00238 
00239         if self.dispatch[event](self, frame, t):
00240             self.t = timer()/60.0
00241         else:
00242             self.t = timer()/60.0 - t  # put back unrecorded delta

def profile.Profile.trace_dispatch_return (   self,
  frame,
  t 
)

Definition at line 305 of file profile.py.

00305 
00306     def trace_dispatch_return(self, frame, t):
00307         if frame is not self.cur[-2]:
00308             assert frame is self.cur[-2].f_back, ("Bad return", self.cur[-3])
00309             self.trace_dispatch_return(self.cur[-2], 0)
00310 
00311         # Prefix "r" means part of the Returning or exiting frame.
00312         # Prefix "p" means part of the Previous or Parent or older frame.
00313 
00314         rpt, rit, ret, rfn, frame, rcur = self.cur
00315         rit = rit + t
00316         frame_total = rit + ret
00317 
00318         ppt, pit, pet, pfn, pframe, pcur = rcur
00319         self.cur = ppt, pit + rpt, pet + frame_total, pfn, pframe, pcur
00320 
00321         timings = self.timings
00322         cc, ns, tt, ct, callers = timings[rfn]
00323         if not ns:
00324             # This is the only occurrence of the function on the stack.
00325             # Else this is a (directly or indirectly) recursive call, and
00326             # its cumulative time will get updated when the topmost call to
00327             # it returns.
00328             ct = ct + frame_total
00329             cc = cc + 1
00330 
00331         if pfn in callers:
00332             callers[pfn] = callers[pfn] + 1  # hack: gather more
00333             # stats such as the amount of time added to ct courtesy
00334             # of this specific call, and the contribution to cc
00335             # courtesy of this call.
00336         else:
00337             callers[pfn] = 1
00338 
00339         timings[rfn] = cc, ns - 1, tt + rit, ct, callers
00340 
00341         return 1
00342 

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

int profile.Profile.bias = 0 [static]

Definition at line 145 of file profile.py.

Definition at line 155 of file profile.py.

Definition at line 151 of file profile.py.

Definition at line 150 of file profile.py.

Definition at line 149 of file profile.py.

Initial value:
{
        "call": trace_dispatch_call,
        "exception": trace_dispatch_exception,
        "return": trace_dispatch_return,
        "c_call": trace_dispatch_c_call,
        "c_exception": trace_dispatch_return,  # the C function returned
        "c_return": trace_dispatch_return,
        }

Definition at line 343 of file profile.py.

Definition at line 160 of file profile.py.

Definition at line 161 of file profile.py.

Definition at line 418 of file profile.py.

Definition at line 193 of file profile.py.

Definition at line 159 of file profile.py.

Definition at line 148 of file profile.py.


The documentation for this class was generated from the following file: