[Python-checkins] CVS: python/dist/src/Doc/lib libprofile.tex,1.36,1.37
Tim Peters
tim_one@users.sourceforge.net
2001年10月06日 20:12:10 -0700
Update of /cvsroot/python/python/dist/src/Doc/lib
In directory usw-pr-cvs1:/tmp/cvs-serv28021/python/Doc/lib
Modified Files:
libprofile.tex
Log Message:
Remove code and docs for the OldProfile and HotProfile classes: code
hasn't worked in years, docs were wrong, and they aren't interesting
anymore regardless.
Index: libprofile.tex
===================================================================
RCS file: /cvsroot/python/python/dist/src/Doc/lib/libprofile.tex,v
retrieving revision 1.36
retrieving revision 1.37
diff -C2 -d -r1.36 -r1.37
*** libprofile.tex 2001年07月06日 20:30:11 1.36
--- libprofile.tex 2001年10月07日 03:12:08 1.37
***************
*** 211,215 ****
\end{verbatim}
! and you would get a list of callers for each of the listed functions.
If you want more functionality, you're going to have to read the
--- 211,215 ----
\end{verbatim}
! and you would get a list of callers for each of the listed functions.
If you want more functionality, you're going to have to read the
***************
*** 310,314 ****
\item[ncalls ]
! for the number of calls,
\item[tottime ]
--- 310,314 ----
\item[ncalls ]
! for the number of calls,
\item[tottime ]
***************
*** 407,411 ****
Abbreviations can be used for any key names, as long as the
abbreviation is unambiguous. The following are the keys currently
! defined:
\begin{tableii}{l|l}{code}{Valid Arg}{Meaning}
--- 407,411 ----
Abbreviations can be used for any key names, as long as the
abbreviation is unambiguous. The following are the keys currently
! defined:
\begin{tableii}{l|l}{code}{Valid Arg}{Meaning}
***************
*** 629,643 ****
The \class{Profile} class of module \module{profile} was written so that
! derived classes could be developed to extend the profiler. Rather
! than describing all the details of such an effort, I'll just present
! the following two examples of derived classes that can be used to do
! profiling. If the reader is an avid Python programmer, then it should
! be possible to use these as a model and create similar (and perchance
! better) profile classes.
! If all you want to do is change how the timer is called, or which
! timer function is used, then the basic class has an option for that in
! the constructor for the class. Consider passing the name of a
! function to call into the constructor:
\begin{verbatim}
--- 629,642 ----
The \class{Profile} class of module \module{profile} was written so that
! derived classes could be developed to extend the profiler. The details
! are not described here, as doing this successfully requires an expert
! understanding of how the \class{Profile} class works internally. Study
! the source code of module \module{profile} carefully if you want to
! pursue this.
! If all you want to do is change how current time is determined (for
! example, to force use of wall-clock time or elapsed process time),
! pass the timing function you want to the \class{Profile} class
! constructor:
\begin{verbatim}
***************
*** 645,808 ****
\end{verbatim}
! The resulting profiler will call \code{your_time_func()} instead of
! \function{os.times()}. The function should return either a single number
! or a list of numbers (like what \function{os.times()} returns). If the
! function returns a single time number, or the list of returned numbers
! has length 2, then you will get an especially fast version of the
! dispatch routine.
! Be warned that you \emph{should} calibrate the profiler class for the
timer function that you choose. For most machines, a timer that
returns a lone integer value will provide the best results in terms of
low overhead during profiling. (\function{os.times()} is
! \emph{pretty} bad, as it returns a tuple of floating point values,
! so all arithmetic is floating point in the profiler!). If you want to
! substitute a better timer in the cleanest fashion, you should derive a
! class, and simply put in the replacement dispatch method that better
handles your timer call, along with the appropriate calibration
constant.
-
- Note that subclasses which override any of the
- \method{trace_dispatch_call()}, \method{trace_dispatch_exception()},
- or \method{trace_dispatch_return()} methods also need to specify a
- dispatch table as well. The table, named \member{dispatch}, should
- have the three keys \code{'call'}, \code{'exception'}, and
- \code{'return'}, each giving the function of the corresponding
- handler. Note that best performance is achieved by using the
- \emph{function} objects for the handlers and not bound methods. This
- is preferred since calling a simple function object executes less code
- in the runtime than calling either bound or unbound methods. For
- example, if the derived profiler overrides only one method, the
- \member{dispatch} table can be built like this:
-
- \begin{verbatim}
- from profile import Profile
-
- class MyProfiler(Profile):
- def trace_dispath_call(self, frame, t):
- # do something interesting here
- ...
-
- dispatch = {
- 'call': trace_dispatch_call,
- 'exception': Profile.__dict__['trace_dispatch_exception'],
- 'return': Profile.__dict__['trace_dispatch_return'],
- }
- \end{verbatim}
-
-
- \subsection{OldProfile Class \label{profile-old}}
-
- The following derived profiler simulates the old style profiler,
- providing errant results on recursive functions. The reason for the
- usefulness of this profiler is that it runs faster (less
- overhead) than the new profiler. It still creates all the caller
- stats, and is quite useful when there is \emph{no} recursion in the
- user's code. It is also a lot more accurate than the old profiler, as
- it does not charge all its overhead time to the user's code.
-
- \begin{verbatim}
- class OldProfile(Profile):
-
- def trace_dispatch_exception(self, frame, t):
- rt, rtt, rct, rfn, rframe, rcur = self.cur
- if rcur and not rframe is frame:
- return self.trace_dispatch_return(rframe, t)
- return 0
-
- def trace_dispatch_call(self, frame, t):
- fn = `frame.f_code`
-
- self.cur = (t, 0, 0, fn, frame, self.cur)
- if self.timings.has_key(fn):
- tt, ct, callers = self.timings[fn]
- self.timings[fn] = tt, ct, callers
- else:
- self.timings[fn] = 0, 0, {}
- return 1
-
- def trace_dispatch_return(self, frame, t):
- rt, rtt, rct, rfn, frame, rcur = self.cur
- rtt = rtt + t
- sft = rtt + rct
-
- pt, ptt, pct, pfn, pframe, pcur = rcur
- self.cur = pt, ptt+rt, pct+sft, pfn, pframe, pcur
-
- tt, ct, callers = self.timings[rfn]
- if callers.has_key(pfn):
- callers[pfn] = callers[pfn] + 1
- else:
- callers[pfn] = 1
- self.timings[rfn] = tt+rtt, ct + sft, callers
-
- return 1
-
- dispatch = {
- "call": trace_dispatch_call,
- "exception": trace_dispatch_exception,
- "return": trace_dispatch_return,
- }
-
- def snapshot_stats(self):
- self.stats = {}
- for func in self.timings.keys():
- tt, ct, callers = self.timings[func]
- callers = callers.copy()
- nc = 0
- for func_caller in callers.keys():
- nc = nc + callers[func_caller]
- self.stats[func] = nc, nc, tt, ct, callers
- \end{verbatim}
-
-
- \subsection{HotProfile Class \label{profile-HotProfile}}
-
- This profiler is the fastest derived profile example. It does not
- calculate caller-callee relationships, and does not calculate
- cumulative time under a function. It only calculates time spent in a
- function, so it runs very quickly (re: very low overhead). In truth,
- the basic profiler is so fast, that is probably not worth the savings
- to give up the data, but this class still provides a nice example.
-
- \begin{verbatim}
- class HotProfile(Profile):
-
- def trace_dispatch_exception(self, frame, t):
- rt, rtt, rfn, rframe, rcur = self.cur
- if rcur and not rframe is frame:
- return self.trace_dispatch_return(rframe, t)
- return 0
-
- def trace_dispatch_call(self, frame, t):
- self.cur = (t, 0, frame, self.cur)
- return 1
-
- def trace_dispatch_return(self, frame, t):
- rt, rtt, frame, rcur = self.cur
-
- rfn = `frame.f_code`
-
- pt, ptt, pframe, pcur = rcur
- self.cur = pt, ptt+rt, pframe, pcur
-
- if self.timings.has_key(rfn):
- nc, tt = self.timings[rfn]
- self.timings[rfn] = nc + 1, rt + rtt + tt
- else:
- self.timings[rfn] = 1, rt + rtt
-
- return 1
-
- dispatch = {
- "call": trace_dispatch_call,
- "exception": trace_dispatch_exception,
- "return": trace_dispatch_return,
- }
-
- def snapshot_stats(self):
- self.stats = {}
- for func in self.timings.keys():
- nc, tt = self.timings[func]
- self.stats[func] = nc, nc, tt, 0, {}
- \end{verbatim}
--- 644,661 ----
\end{verbatim}
! The resulting profiler will then call \code{your_time_func()}.
! The function should return a single number, or a list of
! numbers whose sum is the current time (like what \function{os.times()}
! returns). If the function returns a single time number, or the list of
! returned numbers has length 2, then you will get an especially fast
! version of the dispatch routine.
! Be warned that you should calibrate the profiler class for the
timer function that you choose. For most machines, a timer that
returns a lone integer value will provide the best results in terms of
low overhead during profiling. (\function{os.times()} is
! \emph{pretty} bad, as it returns a tuple of floating point values). If
! you want to substitute a better timer in the cleanest fashion,
! derive a class and hardwire a replacement dispatch method that best
handles your timer call, along with the appropriate calibration
constant.