@@ -210,7 +210,7 @@ \section{Instant Users Manual \label{profile-instant}}
210210p.print_callers(.5, 'init')
211211\end {verbatim }
212212
213- and you would get a list of callers for each of the listed functions.
213+ and you would get a list of callers for each of the listed functions.
214214
215215If you want more functionality, you're going to have to read the
216216manual, or guess what the following functions do:
@@ -309,7 +309,7 @@ \section{Reference Manual}
309309\begin {description }
310310
311311\item [ncalls ]
312- for the number of calls,
312+ for the number of calls,
313313
314314\item [tottime ]
315315for the total time spent in the given function (and excluding time
@@ -406,7 +406,7 @@ \subsection{The \class{Stats} Class \label{profile-stats}}
406406
407407Abbreviations can be used for any key names, as long as the
408408abbreviation is unambiguous. The following are the keys currently
409- defined:
409+ defined:
410410
411411\begin {tableii }{l|l}{code}{Valid Arg}{Meaning}
412412 \lineii {'calls'}{call count}
@@ -628,181 +628,34 @@ \section{Extensions --- Deriving Better Profilers}
628628\nodename {Profiler Extensions}
629629
630630The \class {Profile} class of module \module {profile} was written so that
631- derived classes could be developed to extend the profiler. Rather
632- than describing all the details of such an effort, I'll just present
633- the following two examples of derived classes that can be used to do
634- profiling. If the reader is an avid Python programmer, then it should
635- be possible to use these as a model and create similar (and perchance
636- better) profile classes.
637-
638- If all you want to do is change how the timer is called, or which
639- timer function is used, then the basic class has an option for that in
640- the constructor for the class. Consider passing the name of a
641- function to call into the constructor:
631+ derived classes could be developed to extend the profiler. The details
632+ are not described here, as doing this successfully requires an expert
633+ understanding of how the \class {Profile} class works internally. Study
634+ the source code of module \module {profile} carefully if you want to
635+ pursue this.
636+
637+ If all you want to do is change how current time is determined (for
638+ example, to force use of wall-clock time or elapsed process time),
639+ pass the timing function you want to the \class {Profile} class
640+ constructor:
642641
643642\begin {verbatim }
644643pr = profile.Profile(your_time_func)
645644\end {verbatim }
646645
647- The resulting profiler will call \code {your_time_func()} instead of
648- \function {os.times()}. The function should return either a single number
649- or a list of numbers (like what \function {os.times()} returns). If the
650- function returns a single time number, or the list of returned numbers
651- has length 2, then you will get an especially fast version of the
652- dispatch routine.
646+ The resulting profiler will then call \code {your_time_func()}.
647+ The function should return a single number, or a list of
648+ numbers whose sum is the current time (like what \function {os.times()}
649+ returns). If the function returns a single time number, or the list of
650+ returned numbers has length 2, then you will get an especially fast
651+ version of the dispatch routine.
653652
654- Be warned that you \emph { should } calibrate the profiler class for the
653+ Be warned that you should calibrate the profiler class for the
655654timer function that you choose. For most machines, a timer that
656655returns a lone integer value will provide the best results in terms of
657656low overhead during profiling. (\function {os.times()} is
658- \emph {pretty } bad, as it returns a tuple of floating point values,
659- so all arithmetic is floating point in the profiler!). If you want to
660- substitute a better timer in the cleanest fashion, you should derive a
661- class, and simply put in the replacement dispatch method that better
657+ \emph {pretty } bad, as it returns a tuple of floating point values). If
658+ you want to substitute a better timer in the cleanest fashion,
659+ derive a class and hardwire a replacement dispatch method that best
662660handles your timer call, along with the appropriate calibration
663661constant.
664-
665- Note that subclasses which override any of the
666- \method {trace_dispatch_call()}, \method {trace_dispatch_exception()},
667- or \method {trace_dispatch_return()} methods also need to specify a
668- dispatch table as well. The table, named \member {dispatch}, should
669- have the three keys \code {'call'}, \code {'exception'}, and
670- \code {'return'}, each giving the function of the corresponding
671- handler. Note that best performance is achieved by using the
672- \emph {function } objects for the handlers and not bound methods. This
673- is preferred since calling a simple function object executes less code
674- in the runtime than calling either bound or unbound methods. For
675- example, if the derived profiler overrides only one method, the
676- \member {dispatch} table can be built like this:
677-
678- \begin {verbatim }
679- from profile import Profile
680-
681- class MyProfiler(Profile):
682- def trace_dispath_call(self, frame, t):
683- # do something interesting here
684- ...
685-
686- dispatch = {
687- 'call': trace_dispatch_call,
688- 'exception': Profile.__dict__['trace_dispatch_exception'],
689- 'return': Profile.__dict__['trace_dispatch_return'],
690- }
691- \end {verbatim }
692-
693-
694- \subsection {OldProfile Class \label {profile-old } }
695-
696- The following derived profiler simulates the old style profiler,
697- providing errant results on recursive functions. The reason for the
698- usefulness of this profiler is that it runs faster (less
699- overhead) than the new profiler. It still creates all the caller
700- stats, and is quite useful when there is \emph {no } recursion in the
701- user's code. It is also a lot more accurate than the old profiler, as
702- it does not charge all its overhead time to the user's code.
703-
704- \begin {verbatim }
705- class OldProfile(Profile):
706-
707- def trace_dispatch_exception(self, frame, t):
708- rt, rtt, rct, rfn, rframe, rcur = self.cur
709- if rcur and not rframe is frame:
710- return self.trace_dispatch_return(rframe, t)
711- return 0
712-
713- def trace_dispatch_call(self, frame, t):
714- fn = `frame.f_code`
715-
716- self.cur = (t, 0, 0, fn, frame, self.cur)
717- if self.timings.has_key(fn):
718- tt, ct, callers = self.timings[fn]
719- self.timings[fn] = tt, ct, callers
720- else:
721- self.timings[fn] = 0, 0, {}
722- return 1
723-
724- def trace_dispatch_return(self, frame, t):
725- rt, rtt, rct, rfn, frame, rcur = self.cur
726- rtt = rtt + t
727- sft = rtt + rct
728-
729- pt, ptt, pct, pfn, pframe, pcur = rcur
730- self.cur = pt, ptt+rt, pct+sft, pfn, pframe, pcur
731-
732- tt, ct, callers = self.timings[rfn]
733- if callers.has_key(pfn):
734- callers[pfn] = callers[pfn] + 1
735- else:
736- callers[pfn] = 1
737- self.timings[rfn] = tt+rtt, ct + sft, callers
738-
739- return 1
740-
741- dispatch = {
742- "call": trace_dispatch_call,
743- "exception": trace_dispatch_exception,
744- "return": trace_dispatch_return,
745- }
746-
747- def snapshot_stats(self):
748- self.stats = {}
749- for func in self.timings.keys():
750- tt, ct, callers = self.timings[func]
751- callers = callers.copy()
752- nc = 0
753- for func_caller in callers.keys():
754- nc = nc + callers[func_caller]
755- self.stats[func] = nc, nc, tt, ct, callers
756- \end {verbatim }
757-
758-
759- \subsection {HotProfile Class \label {profile-HotProfile } }
760-
761- This profiler is the fastest derived profile example. It does not
762- calculate caller-callee relationships, and does not calculate
763- cumulative time under a function. It only calculates time spent in a
764- function, so it runs very quickly (re: very low overhead). In truth,
765- the basic profiler is so fast, that is probably not worth the savings
766- to give up the data, but this class still provides a nice example.
767-
768- \begin {verbatim }
769- class HotProfile(Profile):
770-
771- def trace_dispatch_exception(self, frame, t):
772- rt, rtt, rfn, rframe, rcur = self.cur
773- if rcur and not rframe is frame:
774- return self.trace_dispatch_return(rframe, t)
775- return 0
776-
777- def trace_dispatch_call(self, frame, t):
778- self.cur = (t, 0, frame, self.cur)
779- return 1
780-
781- def trace_dispatch_return(self, frame, t):
782- rt, rtt, frame, rcur = self.cur
783-
784- rfn = `frame.f_code`
785-
786- pt, ptt, pframe, pcur = rcur
787- self.cur = pt, ptt+rt, pframe, pcur
788-
789- if self.timings.has_key(rfn):
790- nc, tt = self.timings[rfn]
791- self.timings[rfn] = nc + 1, rt + rtt + tt
792- else:
793- self.timings[rfn] = 1, rt + rtt
794-
795- return 1
796-
797- dispatch = {
798- "call": trace_dispatch_call,
799- "exception": trace_dispatch_exception,
800- "return": trace_dispatch_return,
801- }
802-
803- def snapshot_stats(self):
804- self.stats = {}
805- for func in self.timings.keys():
806- nc, tt = self.timings[func]
807- self.stats[func] = nc, nc, tt, 0, {}
808- \end {verbatim }
0 commit comments