From 0a1fc4e389b9839f2330083fb20e7a466835422f Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Sun, 7 Oct 2001 03:12:08 +0000 Subject: 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. --- Doc/lib/libprofile.tex | 193 ++++++------------------------------------------- Lib/profile.py | 115 ----------------------------- Misc/NEWS | 9 +++ 3 files changed, 32 insertions(+), 285 deletions(-) diff --git a/Doc/lib/libprofile.tex b/Doc/lib/libprofile.tex index 193f5aa..9e4f91b 100644 --- a/Doc/lib/libprofile.tex +++ b/Doc/lib/libprofile.tex @@ -210,7 +210,7 @@ now (\samp{p} is still sorted according to the last criteria) do: p.print_callers(.5, 'init') \end{verbatim} -and you would get a list of callers for each of the listed functions. +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 manual, or guess what the following functions do: @@ -309,7 +309,7 @@ The column headings include: \begin{description} \item[ncalls ] -for the number of calls, +for the number of calls, \item[tottime ] for the total time spent in the given function (and excluding time @@ -406,7 +406,7 @@ all the entries according to their function name, and resolve all ties Abbreviations can be used for any key names, as long as the abbreviation is unambiguous. The following are the keys currently -defined: +defined: \begin{tableii}{l|l}{code}{Valid Arg}{Meaning} \lineii{'calls'}{call count} @@ -628,181 +628,34 @@ at this point, when a constant can be used. \nodename{Profiler Extensions} 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: +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} pr = profile.Profile(your_time_func) \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. +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 \emph{should} calibrate the profiler class for the +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, -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 +\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. - -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} diff --git a/Lib/profile.py b/Lib/profile.py index d291e59..eb3dba8 100755 --- a/Lib/profile.py +++ b/Lib/profile.py @@ -497,121 +497,6 @@ class Profile: ## t = t[0] + t[1] self.ut = t - - -class OldProfile(Profile): - """A derived profiler that simulates the old style profile, providing - errant results on recursive functions. The reason for the usefulness of - this profiler is that it runs faster (i.e., less overhead). It still - creates all the caller stats, and is quite useful when there is *no* - recursion in the user's code. - - This code also shows how easy it is to create a modified profiler. - """ - - 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 - - - -class HotProfile(Profile): - """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 due to its very low overhead. - """ - - 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, {} - - - #**************************************************************************** def Stats(*args): print 'Report generating functions are in the "pstats" module\a' diff --git a/Misc/NEWS b/Misc/NEWS index 0e312c1..30f7df6 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -38,6 +38,15 @@ Library to cause wrong output, including spurious claims of recursive functions and attribution of time spent to the wrong function. + The code and documentation for the derived OldProfile and HotProfile + profiling classes was removed. The code hasn't worked for years (if + you tried to use them, they raised exceptions). OldProfile + intended to reproduce the behavior of the profiler Python used more + than 7 years ago, and isn't interesting anymore. HotProfile intended + to provide a faster profiler (but producing less information), and + that's a worthy goal we intend to meet via a different approach (but + without losing information). + - quopri's encode and decode methods take an optional header parameter, which indicates whether output is intended for the header 'Q' encoding. -- cgit v0.12