[code.view]

[top] / python / PyMOTW / docs / profile / index.html


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>profile, cProfile, and pstats – Performance analysis of Python programs. &mdash; Python Module of the Week</title>
    <link rel="stylesheet" href="../_static/sphinxdoc.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '1.132',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <link rel="author" title="About these documents" href="../about.html" />
    <link rel="top" title="Python Module of the Week" href="../index.html" />
    <link rel="up" title="Debugging and Profiling" href="../profilers.html" />
    <link rel="next" title="timeit – Time the execution of small bits of Python code." href="../timeit/index.html" />
    <link rel="prev" title="Debugging and Profiling" href="../profilers.html" /> 
  </head>
  <body>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="../timeit/index.html" title="timeit – Time the execution of small bits of Python code."
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="../profilers.html" title="Debugging and Profiling"
             accesskey="P">previous</a> |</li>
        <li><a href="../contents.html">PyMOTW</a> &raquo;</li>
          <li><a href="../profilers.html" accesskey="U">Debugging and Profiling</a> &raquo;</li> 
      </ul>
    </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../contents.html">Table Of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">profile, cProfile, and pstats &#8211; Performance analysis of Python programs.</a><ul>
<li><a class="reference internal" href="#run">run()</a></li>
<li><a class="reference internal" href="#runctx">runctx()</a></li>
<li><a class="reference internal" href="#module-pstats">pstats: Saving and Working With Statistics</a></li>
<li><a class="reference internal" href="#limiting-report-contents">Limiting Report Contents</a></li>
<li><a class="reference internal" href="#caller-callee-graphs">Caller / Callee Graphs</a></li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="../profilers.html"
                        title="previous chapter">Debugging and Profiling</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="../timeit/index.html"
                        title="next chapter">timeit &#8211; Time the execution of small bits of Python code.</a></p>
  <h3>This Page</h3>
  <ul class="this-page-menu">
    <li><a href="../_sources/profile/index.txt"
           rel="nofollow">Show Source</a></li>
  </ul>
<div id="searchbox" style="display: none">
  <h3>Quick search</h3>
    <form class="search" action="../search.html" method="get">
      <input type="text" name="q" size="18" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    <p class="searchtip" style="font-size: 90%">
    Enter search terms or a module, class or function name.
    </p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <div class="section" id="module-profile">
<span id="profile-cprofile-and-pstats-performance-analysis-of-python-programs"></span><h1>profile, cProfile, and pstats &#8211; Performance analysis of Python programs.<a class="headerlink" href="#module-profile" title="Permalink to this headline">¶</a></h1>
<span class="target" id="module-cProfile"></span><table class="docutils field-list" frame="void" rules="none">
<col class="field-name" />
<col class="field-body" />
<tbody valign="top">
<tr class="field"><th class="field-name">Purpose:</th><td class="field-body">Performance analysis of Python programs.</td>
</tr>
<tr class="field"><th class="field-name">Python Version:</th><td class="field-body">1.4 and later, these examples are for Python 2.5</td>
</tr>
</tbody>
</table>
<p>The <a class="reference internal" href="#module-profile" title="profile: Performance analysis of Python programs."><tt class="xref py py-mod docutils literal"><span class="pre">profile</span></tt></a> and <a class="reference internal" href="#module-cProfile" title="cProfile: Performance analysis of Python programs."><tt class="xref py py-mod docutils literal"><span class="pre">cProfile</span></tt></a> modules provide APIs for
collecting and analyzing statistics about how Python source consumes
processor resources.</p>
<div class="section" id="run">
<h2>run()<a class="headerlink" href="#run" title="Permalink to this headline">¶</a></h2>
<p>The most basic starting point in the profile module is <tt class="docutils literal"><span class="pre">run()</span></tt>.  It
takes a string statement as argument, and creates a report of the time
spent executing different lines of code while running the statement.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">profile</span>

<span class="k">def</span> <span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="c"># from http://en.literateprograms.org/Fibonacci_numbers_(Python)</span>
    <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span> <span class="mi">0</span>
    <span class="k">elif</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">return</span> <span class="mi">1</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">fib_seq</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="n">seq</span> <span class="o">=</span> <span class="p">[</span> <span class="p">]</span>
    <span class="k">if</span> <span class="n">n</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">seq</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">fib_seq</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
    <span class="n">seq</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">fib</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">seq</span>

<span class="k">print</span> <span class="s">&#39;RAW&#39;</span>
<span class="k">print</span> <span class="s">&#39;=&#39;</span> <span class="o">*</span> <span class="mi">80</span>
<span class="n">profile</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s">&#39;print fib_seq(20); print&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>This recursive version of a fibonacci sequence calculator
<a class="footnote-reference" href="#fibonacci" id="id1">[1]</a> is especially useful for demonstrating the profile
because we can improve the performance so much.  The standard report
format shows a summary and then details for each function executed.</p>
<div class="highlight-python"><pre>$ python profile_fibonacci_raw.py
RAW
================================================================================
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]

         57356 function calls (66 primitive calls) in 0.746 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       21    0.000    0.000    0.000    0.000 :0(append)
       20    0.000    0.000    0.000    0.000 :0(extend)
        1    0.001    0.001    0.001    0.001 :0(setprofile)
        1    0.000    0.000    0.744    0.744 &lt;string&gt;:1(&lt;module&gt;)
        1    0.000    0.000    0.746    0.746 profile:0(print fib_seq(20); print)
        0    0.000             0.000          profile:0(profiler)
 57291/21    0.743    0.000    0.743    0.035 profile_fibonacci_raw.py:13(fib)
     21/1    0.001    0.000    0.744    0.744 profile_fibonacci_raw.py:22(fib_seq)</pre>
</div>
<p>As you can see, it takes 57356 separate function calls and 3/4 of a
second to run.  Since there are only 66 <em>primitive</em> calls, we know
that the vast majority of those 57k calls were recursive.  The details
about where time was spent are broken out by function in the listing
showing the number of calls, total time spent in the function, time
per call (tottime/ncalls), cumulative time spent in a function, and
the ratio of cumulative time to primitive calls.</p>
<p>Not surprisingly, most of the time here is spent calling <tt class="docutils literal"><span class="pre">fib()</span></tt>
repeatedly.  We can add a memoize decorator <a class="footnote-reference" href="#memoize" id="id2">[2]</a> to reduce the
number of recursive calls and have a big impact on the performance of
this function.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">profile</span>

<span class="k">class</span> <span class="nc">memoize</span><span class="p">:</span>
    <span class="c"># from http://avinashv.net/2008/04/python-decorators-syntactic-sugar/</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">function</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">function</span> <span class="o">=</span> <span class="n">function</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">memoized</span> <span class="o">=</span> <span class="p">{}</span>

    <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">memoized</span><span class="p">[</span><span class="n">args</span><span class="p">]</span>
        <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">memoized</span><span class="p">[</span><span class="n">args</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">function</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">memoized</span><span class="p">[</span><span class="n">args</span><span class="p">]</span>

<span class="nd">@memoize</span>
<span class="k">def</span> <span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="c"># from http://en.literateprograms.org/Fibonacci_numbers_(Python)</span>
    <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span> <span class="mi">0</span>
    <span class="k">elif</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">return</span> <span class="mi">1</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">fib</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">fib_seq</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="n">seq</span> <span class="o">=</span> <span class="p">[</span> <span class="p">]</span>
    <span class="k">if</span> <span class="n">n</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">seq</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">fib_seq</span><span class="p">(</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span><span class="p">))</span>
    <span class="n">seq</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">fib</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>
    <span class="k">return</span> <span class="n">seq</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="k">print</span> <span class="s">&#39;MEMOIZED&#39;</span>
    <span class="k">print</span> <span class="s">&#39;=&#39;</span> <span class="o">*</span> <span class="mi">80</span>
    <span class="n">profile</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s">&#39;print fib_seq(20); print&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>By remembering the Fibonacci value at each level we can avoid most of
the recursion and drop down to 145 calls that only take 0.003 seconds.
Also notice that the ncalls count for <tt class="docutils literal"><span class="pre">fib()</span></tt> shows that it <em>never</em>
recurses.</p>
<div class="highlight-python"><pre>$ python profile_fibonacci_memoized.py
MEMOIZED
================================================================================
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]

         145 function calls (87 primitive calls) in 0.003 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       21    0.000    0.000    0.000    0.000 :0(append)
       20    0.000    0.000    0.000    0.000 :0(extend)
        1    0.001    0.001    0.001    0.001 :0(setprofile)
        1    0.000    0.000    0.002    0.002 &lt;string&gt;:1(&lt;module&gt;)
        1    0.000    0.000    0.003    0.003 profile:0(print fib_seq(20); print)
        0    0.000             0.000          profile:0(profiler)
    59/21    0.001    0.000    0.001    0.000 profile_fibonacci_memoized.py:19(__call__)
       21    0.000    0.000    0.001    0.000 profile_fibonacci_memoized.py:26(fib)
     21/1    0.001    0.000    0.002    0.002 profile_fibonacci_memoized.py:36(fib_seq)</pre>
</div>
</div>
<div class="section" id="runctx">
<h2>runctx()<a class="headerlink" href="#runctx" title="Permalink to this headline">¶</a></h2>
<p>Sometimes, instead of constructing a complex expression for <tt class="docutils literal"><span class="pre">run()</span></tt>,
it is easier to build a simple expression and pass it parameters
through a context, using <tt class="docutils literal"><span class="pre">runctx()</span></tt>.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">profile</span>
<span class="kn">from</span> <span class="nn">profile_fibonacci_memoized</span> <span class="kn">import</span> <span class="n">fib</span><span class="p">,</span> <span class="n">fib_seq</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="n">profile</span><span class="o">.</span><span class="n">runctx</span><span class="p">(</span><span class="s">&#39;print fib_seq(n); print&#39;</span><span class="p">,</span> <span class="nb">globals</span><span class="p">(),</span> <span class="p">{</span><span class="s">&#39;n&#39;</span><span class="p">:</span><span class="mi">20</span><span class="p">})</span>
</pre></div>
</div>
<p>In this example, the value of &#8220;n&#8221; is passed through the local variable
context instead of being embedded directly in the statement passed to
<tt class="docutils literal"><span class="pre">runctx()</span></tt>.</p>
<div class="highlight-python"><pre>$ python profile_runctx.py
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]

         145 function calls (87 primitive calls) in 0.003 CPU seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       21    0.000    0.000    0.000    0.000 :0(append)
       20    0.000    0.000    0.000    0.000 :0(extend)
        1    0.001    0.001    0.001    0.001 :0(setprofile)
        1    0.000    0.000    0.002    0.002 &lt;string&gt;:1(&lt;module&gt;)
        1    0.000    0.000    0.003    0.003 profile:0(print fib_seq(n); print)
        0    0.000             0.000          profile:0(profiler)
    59/21    0.001    0.000    0.001    0.000 profile_fibonacci_memoized.py:19(__call__)
       21    0.000    0.000    0.001    0.000 profile_fibonacci_memoized.py:26(fib)
     21/1    0.001    0.000    0.002    0.002 profile_fibonacci_memoized.py:36(fib_seq)</pre>
</div>
</div>
<div class="section" id="module-pstats">
<span id="pstats-saving-and-working-with-statistics"></span><h2>pstats: Saving and Working With Statistics<a class="headerlink" href="#module-pstats" title="Permalink to this headline">¶</a></h2>
<p>The standard report created by the <a class="reference internal" href="#module-profile" title="profile: Performance analysis of Python programs."><tt class="xref py py-mod docutils literal"><span class="pre">profile</span></tt></a> functions is not
very flexible.  If it doesn&#8217;t meet your needs, you can produce your
own reports by saving the raw profiling data from <tt class="docutils literal"><span class="pre">run()</span></tt> and
<tt class="docutils literal"><span class="pre">runctx()</span></tt> and processing it separately with the <strong>Stats</strong> class
from <a class="reference internal" href="#module-pstats" title="pstats: Manipulate and analyze profile statistics."><tt class="xref py py-mod docutils literal"><span class="pre">pstats</span></tt></a>.</p>
<p>For example, to run several iterations of the same test and combine
the results, you could do something like this:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">profile</span>
<span class="kn">import</span> <span class="nn">pstats</span>
<span class="kn">from</span> <span class="nn">profile_fibonacci_memoized</span> <span class="kn">import</span> <span class="n">fib</span><span class="p">,</span> <span class="n">fib_seq</span>

<span class="c"># Create 5 set of stats</span>
<span class="n">filenames</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
    <span class="n">filename</span> <span class="o">=</span> <span class="s">&#39;profile_stats_</span><span class="si">%d</span><span class="s">.stats&#39;</span> <span class="o">%</span> <span class="n">i</span>
    <span class="n">profile</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s">&#39;print </span><span class="si">%d</span><span class="s">, fib_seq(20)&#39;</span> <span class="o">%</span> <span class="n">i</span><span class="p">,</span> <span class="n">filename</span><span class="p">)</span>

<span class="c"># Read all 5 stats files into a single object</span>
<span class="n">stats</span> <span class="o">=</span> <span class="n">pstats</span><span class="o">.</span><span class="n">Stats</span><span class="p">(</span><span class="s">&#39;profile_stats_0.stats&#39;</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">):</span>
    <span class="n">stats</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s">&#39;profile_stats_</span><span class="si">%d</span><span class="s">.stats&#39;</span> <span class="o">%</span> <span class="n">i</span><span class="p">)</span>

<span class="c"># Clean up filenames for the report</span>
<span class="n">stats</span><span class="o">.</span><span class="n">strip_dirs</span><span class="p">()</span>

<span class="c"># Sort the statistics by the cumulative time spent in the function</span>
<span class="n">stats</span><span class="o">.</span><span class="n">sort_stats</span><span class="p">(</span><span class="s">&#39;cumulative&#39;</span><span class="p">)</span>

<span class="n">stats</span><span class="o">.</span><span class="n">print_stats</span><span class="p">()</span>
</pre></div>
</div>
<p>The output report is sorted in descending order of cumulative time
spent in the function and the directory names are removed from the
printed filenames to conserve horizontal space.</p>
<div class="highlight-python"><pre>$ python profile_stats.py
0 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
1 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
2 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
3 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
4 [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
Sun Aug 31 11:29:36 2008    profile_stats_0.stats
Sun Aug 31 11:29:36 2008    profile_stats_1.stats
Sun Aug 31 11:29:36 2008    profile_stats_2.stats
Sun Aug 31 11:29:36 2008    profile_stats_3.stats
Sun Aug 31 11:29:36 2008    profile_stats_4.stats

         489 function calls (351 primitive calls) in 0.008 CPU seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        5    0.000    0.000    0.007    0.001 &lt;string&gt;:1(&lt;module&gt;)
    105/5    0.004    0.000    0.007    0.001 profile_fibonacci_memoized.py:36(fib_seq)
        1    0.000    0.000    0.003    0.003 profile:0(print 0, fib_seq(20))
  143/105    0.001    0.000    0.002    0.000 profile_fibonacci_memoized.py:19(__call__)
        1    0.000    0.000    0.001    0.001 profile:0(print 4, fib_seq(20))
        1    0.000    0.000    0.001    0.001 profile:0(print 1, fib_seq(20))
        1    0.000    0.000    0.001    0.001 profile:0(print 2, fib_seq(20))
        1    0.000    0.000    0.001    0.001 profile:0(print 3, fib_seq(20))
       21    0.000    0.000    0.001    0.000 profile_fibonacci_memoized.py:26(fib)
      100    0.001    0.000    0.001    0.000 :0(extend)
      105    0.001    0.000    0.001    0.000 :0(append)
        5    0.001    0.000    0.001    0.000 :0(setprofile)
        0    0.000             0.000          profile:0(profiler)</pre>
</div>
</div>
<div class="section" id="limiting-report-contents">
<h2>Limiting Report Contents<a class="headerlink" href="#limiting-report-contents" title="Permalink to this headline">¶</a></h2>
<p>Since we are studying the performance of <tt class="docutils literal"><span class="pre">fib()</span></tt> and <tt class="docutils literal"><span class="pre">fib_seq()</span></tt>,
we can also restrict the output report to only include those functions
using a regular expression to match the <tt class="docutils literal"><span class="pre">filename:lineno(function)</span></tt>
values we want.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">profile</span>
<span class="kn">import</span> <span class="nn">pstats</span>
<span class="kn">from</span> <span class="nn">profile_fibonacci_memoized</span> <span class="kn">import</span> <span class="n">fib</span><span class="p">,</span> <span class="n">fib_seq</span>

<span class="c"># Read all 5 stats files into a single object</span>
<span class="n">stats</span> <span class="o">=</span> <span class="n">pstats</span><span class="o">.</span><span class="n">Stats</span><span class="p">(</span><span class="s">&#39;profile_stats_0.stats&#39;</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">):</span>
    <span class="n">stats</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s">&#39;profile_stats_</span><span class="si">%d</span><span class="s">.stats&#39;</span> <span class="o">%</span> <span class="n">i</span><span class="p">)</span>
<span class="n">stats</span><span class="o">.</span><span class="n">strip_dirs</span><span class="p">()</span>
<span class="n">stats</span><span class="o">.</span><span class="n">sort_stats</span><span class="p">(</span><span class="s">&#39;cumulative&#39;</span><span class="p">)</span>

<span class="c"># limit output to lines with &quot;(fib&quot; in them</span>
<span class="n">stats</span><span class="o">.</span><span class="n">print_stats</span><span class="p">(</span><span class="s">&#39;\(fib&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>The regular expression includes a literal left paren (<tt class="docutils literal"><span class="pre">(</span></tt>) to match
against the function name portion of the location value.</p>
<div class="highlight-python"><pre>$ python profile_stats_restricted.py
Sun Aug 31 11:29:36 2008    profile_stats_0.stats
Sun Aug 31 11:29:36 2008    profile_stats_1.stats
Sun Aug 31 11:29:36 2008    profile_stats_2.stats
Sun Aug 31 11:29:36 2008    profile_stats_3.stats
Sun Aug 31 11:29:36 2008    profile_stats_4.stats

         489 function calls (351 primitive calls) in 0.008 CPU seconds

   Ordered by: cumulative time
   List reduced from 13 to 2 due to restriction &lt;'\\(fib'&gt;

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    105/5    0.004    0.000    0.007    0.001 profile_fibonacci_memoized.py:36(fib_seq)
       21    0.000    0.000    0.001    0.000 profile_fibonacci_memoized.py:26(fib)</pre>
</div>
</div>
<div class="section" id="caller-callee-graphs">
<h2>Caller / Callee Graphs<a class="headerlink" href="#caller-callee-graphs" title="Permalink to this headline">¶</a></h2>
<p><strong>Stats</strong> also includes methods for printing the callers and callees
of functions.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">profile</span>
<span class="kn">import</span> <span class="nn">pstats</span>
<span class="kn">from</span> <span class="nn">profile_fibonacci_memoized</span> <span class="kn">import</span> <span class="n">fib</span><span class="p">,</span> <span class="n">fib_seq</span>

<span class="c"># Read all 5 stats files into a single object</span>
<span class="n">stats</span> <span class="o">=</span> <span class="n">pstats</span><span class="o">.</span><span class="n">Stats</span><span class="p">(</span><span class="s">&#39;profile_stats_0.stats&#39;</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">5</span><span class="p">):</span>
    <span class="n">stats</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s">&#39;profile_stats_</span><span class="si">%d</span><span class="s">.stats&#39;</span> <span class="o">%</span> <span class="n">i</span><span class="p">)</span>
<span class="n">stats</span><span class="o">.</span><span class="n">strip_dirs</span><span class="p">()</span>
<span class="n">stats</span><span class="o">.</span><span class="n">sort_stats</span><span class="p">(</span><span class="s">&#39;cumulative&#39;</span><span class="p">)</span>

<span class="k">print</span> <span class="s">&#39;INCOMING CALLERS:&#39;</span>
<span class="n">stats</span><span class="o">.</span><span class="n">print_callers</span><span class="p">(</span><span class="s">&#39;\(fib&#39;</span><span class="p">)</span>

<span class="k">print</span> <span class="s">&#39;OUTGOING CALLEES:&#39;</span>
<span class="n">stats</span><span class="o">.</span><span class="n">print_callees</span><span class="p">(</span><span class="s">&#39;\(fib&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>The arguments to <tt class="docutils literal"><span class="pre">print_callers()</span></tt> and <tt class="docutils literal"><span class="pre">print_callees()</span></tt> work the
same as the restriction arguments to <tt class="docutils literal"><span class="pre">print_stats()</span></tt>.  The output
shows the caller, callee, and cumulative time.</p>
<div class="highlight-python"><pre>$ python profile_stats_callers.py
INCOMING CALLERS:
   Ordered by: cumulative time
   List reduced from 13 to 2 due to restriction &lt;'\\(fib'&gt;

Function                                   was called by...
profile_fibonacci_memoized.py:36(fib_seq)  &lt;- &lt;string&gt;:1(&lt;module&gt;)(5)    0.007
                                              profile_fibonacci_memoized.py:36(fib_seq)(100)    0.007
profile_fibonacci_memoized.py:26(fib)      &lt;- profile_fibonacci_memoized.py:19(__call__)(21)    0.002


OUTGOING CALLEES:
   Ordered by: cumulative time
   List reduced from 13 to 2 due to restriction &lt;'\\(fib'&gt;

Function                                   called...
profile_fibonacci_memoized.py:36(fib_seq)  -&gt; :0(append)(105)    0.001
                                              :0(extend)(100)    0.001
                                              profile_fibonacci_memoized.py:19(__call__)(105)    0.002
                                              profile_fibonacci_memoized.py:36(fib_seq)(100)    0.007
profile_fibonacci_memoized.py:26(fib)      -&gt; profile_fibonacci_memoized.py:19(__call__)(38)    0.002</pre>
</div>
<div class="admonition-see-also admonition seealso">
<p class="first admonition-title">See also</p>
<dl class="docutils">
<dt><a class="reference external" href="http://docs.python.org/lib/module-profile.html">profile and cProfile</a></dt>
<dd>Standard library documentation for this module.</dd>
<dt><a class="reference external" href="http://docs.python.org/lib/profile-stats.html">pstats</a></dt>
<dd>Standard library documentation for pstats.</dd>
<dt><a class="reference external" href="http://code.google.com/p/jrfonseca/wiki/Gprof2Dot">Gprof2Dot</a></dt>
<dd>Visualization tool for profile output data.</dd>
</dl>
<table class="docutils footnote" frame="void" id="fibonacci" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1">[1]</a></td><td><em>Fibonacci numbers (Python) - LiteratePrograms</em> via <a class="reference external" href="http://en.literateprograms.org/Fibonacci_numbers_(Python">http://en.literateprograms.org/Fibonacci_numbers_(Python</a>)</td></tr>
</tbody>
</table>
<table class="last docutils footnote" frame="void" id="memoize" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id2">[2]</a></td><td><em>Python Decorators: Syntactic Sugar | avinash.vora</em> from <a class="reference external" href="http://avinashv.net/2008/04/python-decorators-syntactic-sugar/">http://avinashv.net/2008/04/python-decorators-syntactic-sugar/</a></td></tr>
</tbody>
</table>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="../timeit/index.html" title="timeit – Time the execution of small bits of Python code."
             >next</a> |</li>
        <li class="right" >
          <a href="../profilers.html" title="Debugging and Profiling"
             >previous</a> |</li>
        <li><a href="../contents.html">PyMOTW</a> &raquo;</li>
          <li><a href="../profilers.html" >Debugging and Profiling</a> &raquo;</li> 
      </ul>
    </div>
    <div class="footer">
      &copy; Copyright Doug Hellmann.
      Last updated on Oct 24, 2010.
      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.

    <br/><a href="http://creativecommons.org/licenses/by-nc-sa/3.0/us/" rel="license"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-nc-sa/3.0/us/88x31.png"/></a>
    
    </div>
  </body>
</html>

[top] / python / PyMOTW / docs / profile / index.html

contact | logmethods.com