python-peps/pep-3146/index.html

1788 lines
126 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 3146 Merging Unladen Swallow into CPython | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-3146/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 3146 Merging Unladen Swallow into CPython | peps.python.org'>
<meta property="og:description" content="This PEP proposes the merger of the Unladen Swallow project 3 into CPythons source tree. Unladen Swallow is an open-source branch of CPython focused on performance. Unladen Swallow is source-compatible with valid Python 2.6.4 applications and C extensi...">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-3146/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="This PEP proposes the merger of the Unladen Swallow project 3 into CPythons source tree. Unladen Swallow is an open-source branch of CPython focused on performance. Unladen Swallow is source-compatible with valid Python 2.6.4 applications and C extensi...">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 3146</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 3146 Merging Unladen Swallow into CPython</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Collin Winter &lt;collinwinter&#32;&#97;t&#32;google.com&gt;,
Jeffrey Yasskin &lt;jyasskin&#32;&#97;t&#32;google.com&gt;,
Reid Kleckner &lt;rnk&#32;&#97;t&#32;mit.edu&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Removed from consideration by sponsor or authors">Withdrawn</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">01-Jan-2010</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">3.3</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even"><p></p></dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#pep-withdrawal">PEP Withdrawal</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale-implementation">Rationale, Implementation</a><ul>
<li><a class="reference internal" href="#alternatives">Alternatives</a></li>
</ul>
</li>
<li><a class="reference internal" href="#performance">Performance</a><ul>
<li><a class="reference internal" href="#benchmarks">Benchmarks</a></li>
<li><a class="reference internal" href="#performance-vs-cpython-2-6-4">Performance vs CPython 2.6.4</a></li>
<li><a class="reference internal" href="#memory-usage">Memory Usage</a></li>
<li><a class="reference internal" href="#start-up-time">Start-up Time</a></li>
<li><a class="reference internal" href="#binary-size">Binary Size</a></li>
<li><a class="reference internal" href="#performance-retrospective">Performance Retrospective</a></li>
</ul>
</li>
<li><a class="reference internal" href="#correctness-and-compatibility">Correctness and Compatibility</a><ul>
<li><a class="reference internal" href="#known-incompatibilities">Known Incompatibilities</a></li>
</ul>
</li>
<li><a class="reference internal" href="#platform-support">Platform Support</a></li>
<li><a class="reference internal" href="#impact-on-cpython-development">Impact on CPython Development</a><ul>
<li><a class="reference internal" href="#experimenting-with-changes-to-python-or-cpython-bytecode">Experimenting with Changes to Python or CPython Bytecode</a></li>
<li><a class="reference internal" href="#debugging">Debugging</a></li>
<li><a class="reference internal" href="#profiling">Profiling</a></li>
<li><a class="reference internal" href="#addition-of-c-to-cpython">Addition of C++ to CPython</a></li>
<li><a class="reference internal" href="#managing-llvm-releases-c-api-changes">Managing LLVM Releases, C++ API Changes</a></li>
<li><a class="reference internal" href="#building-cpython">Building CPython</a></li>
</ul>
</li>
<li><a class="reference internal" href="#proposed-merge-plan">Proposed Merge Plan</a><ul>
<li><a class="reference internal" href="#contingency-plans">Contingency Plans</a></li>
</ul>
</li>
<li><a class="reference internal" href="#future-work">Future Work</a></li>
<li><a class="reference internal" href="#unladen-swallow-community">Unladen Swallow Community</a></li>
<li><a class="reference internal" href="#licensing">Licensing</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
</details></section>
<section id="pep-withdrawal">
<h2><a class="toc-backref" href="#pep-withdrawal" role="doc-backlink">PEP Withdrawal</a></h2>
<p>With Unladen Swallow going the way of the Norwegian Blue <a class="footnote-reference brackets" href="#us-post-mortem" id="id1">[1]</a>
<a class="footnote-reference brackets" href="#dead-parrot" id="id2">[2]</a>, this PEP has been deemed to have been withdrawn.</p>
</section>
<section id="abstract">
<h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2>
<p>This PEP proposes the merger of the Unladen Swallow project <a class="footnote-reference brackets" href="#us" id="id3">[3]</a> into
CPythons source tree. Unladen Swallow is an open-source branch of CPython
focused on performance. Unladen Swallow is source-compatible with valid Python
2.6.4 applications and C extension modules.</p>
<p>Unladen Swallow adds a just-in-time (JIT) compiler to CPython, allowing for the
compilation of selected Python code to optimized machine code. Beyond classical
static compiler optimizations, Unladen Swallows JIT compiler takes advantage of
data collected at runtime to make checked assumptions about code behaviour,
allowing the production of faster machine code.</p>
<p>This PEP proposes to integrate Unladen Swallow into CPythons development tree
in a separate <code class="docutils literal notranslate"><span class="pre">py3k-jit</span></code> branch, targeted for eventual merger with the main
<code class="docutils literal notranslate"><span class="pre">py3k</span></code> branch. While Unladen Swallow is by no means finished or perfect, we
feel that Unladen Swallow has reached sufficient maturity to warrant
incorporation into CPythons roadmap. We have sought to create a stable platform
that the wider CPython development team can build upon, a platform that will
yield increasing performance for years to come.</p>
<p>This PEP will detail Unladen Swallows implementation and how it differs from
CPython 2.6.4; the benchmarks used to measure performance; the tools used to
ensure correctness and compatibility; the impact on CPythons current platform
support; and the impact on the CPython core development process. The PEP
concludes with a proposed merger plan and brief notes on possible directions
for future work.</p>
<p>We seek the following from the BDFL:</p>
<ul class="simple">
<li>Approval for the overall concept of adding a just-in-time compiler to CPython,
following the design laid out below.</li>
<li>Permission to continue working on the just-in-time compiler in the CPython
source tree.</li>
<li>Permission to eventually merge the just-in-time compiler into the <code class="docutils literal notranslate"><span class="pre">py3k</span></code>
branch once all blocking issues <a class="footnote-reference brackets" href="#us-punchlist" id="id4">[31]</a> have been addressed.</li>
<li>A pony.</li>
</ul>
</section>
<section id="rationale-implementation">
<h2><a class="toc-backref" href="#rationale-implementation" role="doc-backlink">Rationale, Implementation</a></h2>
<p>Many companies and individuals would like Python to be faster, to enable its
use in more projects. Google is one such company.</p>
<p>Unladen Swallow is a Google-sponsored branch of CPython, initiated to improve
the performance of Googles numerous Python libraries, tools and applications.
To make the adoption of Unladen Swallow as easy as possible, the project
initially aimed at four goals:</p>
<ul class="simple">
<li>A performance improvement of 5x over the baseline of CPython 2.6.4 for
single-threaded code.</li>
<li>100% source compatibility with valid CPython 2.6 applications.</li>
<li>100% source compatibility with valid CPython 2.6 C extension modules.</li>
<li>Design for eventual merger back into CPython.</li>
</ul>
<p>We chose 2.6.4 as our baseline because Google uses CPython 2.4 internally, and
jumping directly from CPython 2.4 to CPython 3.x was considered infeasible.</p>
<p>To achieve the desired performance, Unladen Swallow has implemented a
just-in-time (JIT) compiler <a class="footnote-reference brackets" href="#jit" id="id5">[51]</a> in the tradition of Urs Hoelzles work on
Self <a class="footnote-reference brackets" href="#urs-self" id="id6">[52]</a>, gathering feedback at runtime and using that to inform
compile-time optimizations. This is similar to the approach taken by the current
breed of JavaScript engines <a class="footnote-reference brackets" href="#v8" id="id7">[59]</a>, <a class="footnote-reference brackets" href="#squirrelfishextreme" id="id8">[60]</a>; most Java virtual
machines <a class="footnote-reference brackets" href="#hotspot" id="id9">[64]</a>; Rubinius <a class="footnote-reference brackets" href="#rubinius" id="id10">[61]</a>, MacRuby <a class="footnote-reference brackets" href="#macruby" id="id11">[63]</a>, and other Ruby
implementations; Psyco <a class="footnote-reference brackets" href="#psyco" id="id12">[65]</a>; and others.</p>
<p>We explicitly reject any suggestion that our ideas are original. We have sought
to reuse the published work of other researchers wherever possible. If we have
done any original work, it is by accident. We have tried, as much as possible,
to take good ideas from all corners of the academic and industrial community. A
partial list of the research papers that have informed Unladen Swallow is
available on the Unladen Swallow wiki <a class="footnote-reference brackets" href="#us-relevantpapers" id="id13">[54]</a>.</p>
<p>The key observation about optimizing dynamic languages is that they are only
dynamic in theory; in practice, each individual function or snippet of code is
relatively static, using a stable set of types and child functions. The current
CPython bytecode interpreter assumes the worst about the code it is running,
that at any moment the user might override the <code class="docutils literal notranslate"><span class="pre">len()</span></code> function or pass a
never-before-seen type into a function. In practice this never happens, but user
code pays for that support. Unladen Swallow takes advantage of the relatively
static nature of user code to improve performance.</p>
<p>At a high level, the Unladen Swallow JIT compiler works by translating a
functions CPython bytecode to platform-specific machine code, using data
collected at runtime, as well as classical compiler optimizations, to improve
the quality of the generated machine code. Because we only want to spend
resources compiling Python code that will actually benefit the runtime of the
program, an online heuristic is used to assess how hot a given function is. Once
the hotness value for a function crosses a given threshold, it is selected for
compilation and optimization. Until a function is judged hot, however, it runs
in the standard CPython eval loop, which in Unladen Swallow has been
instrumented to record interesting data about each bytecode executed. This
runtime data is used to reduce the flexibility of the generated machine code,
allowing us to optimize for the common case. For example, we collect data on</p>
<ul class="simple">
<li>Whether a branch was taken/not taken. If a branch is never taken, we will not
compile it to machine code.</li>
<li>Types used by operators. If we find that <code class="docutils literal notranslate"><span class="pre">a</span> <span class="pre">+</span> <span class="pre">b</span></code> is only ever adding
integers, the generated machine code for that snippet will not support adding
floats.</li>
<li>Functions called at each callsite. If we find that a particular <code class="docutils literal notranslate"><span class="pre">foo()</span></code>
callsite is always calling the same <code class="docutils literal notranslate"><span class="pre">foo</span></code> function, we can optimize the
call or inline it away</li>
</ul>
<p>Refer to <a class="footnote-reference brackets" href="#us-llvm-notes" id="id14">[55]</a> for a complete list of data points gathered and how
they are used.</p>
<p>However, if by chance the historically-untaken branch is now taken, or some
integer-optimized <code class="docutils literal notranslate"><span class="pre">a</span> <span class="pre">+</span> <span class="pre">b</span></code> snippet receives two strings, we must support this.
We cannot change Python semantics. Each of these sections of optimized machine
code is preceded by a <code class="docutils literal notranslate"><span class="pre">guard</span></code>, which checks whether the simplifying
assumptions we made when optimizing still hold. If the assumptions are still
valid, we run the optimized machine code; if they are not, we revert back to
the interpreter and pick up where we left off.</p>
<p>We have chosen to reuse a set of existing compiler libraries called LLVM
<a class="footnote-reference brackets" href="#llvm" id="id15">[4]</a> for code generation and code optimization. This has saved our small
team from needing to understand and debug code generation on multiple machine
instruction sets and from needing to implement a large set of classical compiler
optimizations. The project would not have been possible without such code reuse.
We have found LLVM easy to modify and its community receptive to our suggestions
and modifications.</p>
<p>In somewhat more depth, Unladen Swallows JIT works by compiling CPython
bytecode to LLVMs own intermediate representation (IR) <a class="footnote-reference brackets" href="#llvm-langref" id="id16">[95]</a>, taking
into account any runtime data from the CPython eval loop. We then run a set of
LLVMs built-in optimization passes, producing a smaller, optimized version of
the original LLVM IR. LLVM then lowers the IR to platform-specific machine code,
performing register allocation, instruction scheduling, and any necessary
relocations. This arrangement of the compilation pipeline allows the LLVM-based
JIT to be easily omitted from a compiled <code class="docutils literal notranslate"><span class="pre">python</span></code> binary by passing
<code class="docutils literal notranslate"><span class="pre">--without-llvm</span></code> to <code class="docutils literal notranslate"><span class="pre">./configure</span></code>; various use cases for this flag are
discussed later.</p>
<p>For a complete detailing of how Unladen Swallow works, consult the Unladen
Swallow documentation <a class="footnote-reference brackets" href="#us-projectplan" id="id17">[53]</a>, <a class="footnote-reference brackets" href="#us-llvm-notes" id="id18">[55]</a>.</p>
<p>Unladen Swallow has focused on improving the performance of single-threaded,
pure-Python code. We have not made an effort to remove CPythons global
interpreter lock (GIL); we feel this is separate from our work, and due to its
sensitivity, is best done in a mainline development branch. We considered
making GIL-removal a part of Unladen Swallow, but were concerned by the
possibility of introducing subtle bugs when porting our work from CPython 2.6
to 3.x.</p>
<p>A JIT compiler is an extremely versatile tool, and we have by no means
exhausted its full potential. We have tried to create a sufficiently flexible
framework that the wider CPython development community can build upon it for
years to come, extracting increased performance in each subsequent release.</p>
<section id="alternatives">
<h3><a class="toc-backref" href="#alternatives" role="doc-backlink">Alternatives</a></h3>
<p>There are number of alternative strategies for improving Python performance
which we considered, but found unsatisfactory.</p>
<ul>
<li><em>Cython, Shedskin</em>: Cython <a class="footnote-reference brackets" href="#cython" id="id19">[102]</a> and Shedskin <a class="footnote-reference brackets" href="#shedskin" id="id20">[103]</a> are both
static compilers for Python. We view these as useful-but-limited workarounds
for CPythons historically-poor performance. Shedskin does not support the
full Python standard library <a class="footnote-reference brackets" href="#shedskin-library-limits" id="id21">[104]</a>, while Cython
requires manual Cython-specific annotations for optimum performance.<p>Static compilers like these are useful for writing extension modules without
worrying about reference counting, but because they are static, ahead-of-time
compilers, they cannot optimize the full range of code under consideration by
a just-in-time compiler informed by runtime data.</p>
</li>
<li><em>IronPython</em>: IronPython <a class="footnote-reference brackets" href="#ironpython" id="id22">[107]</a> is Python on Microsofts .Net
platform. It is not actively tested on Mono <a class="footnote-reference brackets" href="#mono" id="id23">[108]</a>, meaning that it is
essentially Windows-only, making it unsuitable as a general CPython
replacement.</li>
<li><em>Jython</em>: Jython <a class="footnote-reference brackets" href="#jython" id="id24">[109]</a> is a complete implementation of Python 2.5, but
is significantly slower than Unladen Swallow (3-5x on measured benchmarks) and
has no support for CPython extension modules <a class="footnote-reference brackets" href="#jython-c-ext" id="id25">[110]</a>, which would
make migration of large applications prohibitively expensive.</li>
<li><em>Psyco</em>: Psyco <a class="footnote-reference brackets" href="#psyco" id="id26">[65]</a> is a specializing JIT compiler for CPython,
implemented as an extension module. It primarily improves performance for
numerical code. Pros: exists; makes some code faster. Cons: 32-bit only, with
no plans for 64-bit support; supports x86 only; very difficult to maintain;
incompatible with SSE2 optimized code due to alignment issues.</li>
<li><em>PyPy</em>: PyPy <a class="footnote-reference brackets" href="#pypy" id="id27">[66]</a> has good performance on numerical code, but is slower
than Unladen Swallow on some workloads. Migration of large applications from
CPython to PyPy would be prohibitively expensive: PyPys JIT compiler supports
only 32-bit x86 code generation; important modules, such as MySQLdb and
pycrypto, do not build against PyPy; PyPy does not offer an embedding API,
much less the same API as CPython.</li>
<li><em>PyV8</em>: PyV8 <a class="footnote-reference brackets" href="#pyv8" id="id28">[111]</a> is an alpha-stage experimental Python-to-JavaScript
compiler that runs on top of V8. PyV8 does not implement the whole Python
language, and has no support for CPython extension modules.</li>
<li><em>WPython</em>: WPython <a class="footnote-reference brackets" href="#wpython" id="id29">[105]</a> is a wordcode-based reimplementation of
CPythons interpreter loop. While it provides a modest improvement to
interpreter performance <a class="footnote-reference brackets" href="#wpython-performance" id="id30">[106]</a>, it is not an either-or
substitute for a just-in-time compiler. An interpreter will never be as fast
as optimized machine code. We view WPython and similar interpreter
enhancements as complementary to our work, rather than as competitors.</li>
</ul>
</section>
</section>
<section id="performance">
<h2><a class="toc-backref" href="#performance" role="doc-backlink">Performance</a></h2>
<section id="benchmarks">
<h3><a class="toc-backref" href="#benchmarks" role="doc-backlink">Benchmarks</a></h3>
<p>Unladen Swallow has developed a fairly large suite of benchmarks, ranging from
synthetic microbenchmarks designed to test a single feature up through
whole-application macrobenchmarks. The inspiration for these benchmarks has come
variously from third-party contributors (in the case of the <code class="docutils literal notranslate"><span class="pre">html5lib</span></code>
benchmark), Googles own internal workloads (<code class="docutils literal notranslate"><span class="pre">slowspitfire</span></code>, <code class="docutils literal notranslate"><span class="pre">pickle</span></code>,
<code class="docutils literal notranslate"><span class="pre">unpickle</span></code>), as well as tools and libraries in heavy use throughout the wider
Python community (<code class="docutils literal notranslate"><span class="pre">django</span></code>, <code class="docutils literal notranslate"><span class="pre">2to3</span></code>, <code class="docutils literal notranslate"><span class="pre">spambayes</span></code>). These benchmarks are run
through a single interface called <code class="docutils literal notranslate"><span class="pre">perf.py</span></code> that takes care of collecting
memory usage information, graphing performance, and running statistics on the
benchmark results to ensure significance.</p>
<p>The full list of available benchmarks is available on the Unladen Swallow wiki
<a class="footnote-reference brackets" href="#us-benchmarks" id="id31">[43]</a>, including instructions on downloading and running the
benchmarks for yourself. All our benchmarks are open-source; none are
Google-proprietary. We believe this collection of benchmarks serves as a useful
tool to benchmark any complete Python implementation, and indeed, PyPy is
already using these benchmarks for their own performance testing
<a class="footnote-reference brackets" href="#pypy-bmarks" id="id32">[81]</a>, <a class="footnote-reference brackets" href="#us-wider-perf-issue" id="id33">[96]</a>. We welcome this, and we seek
additional workloads for the benchmark suite from the Python community.</p>
<p>We have focused our efforts on collecting macrobenchmarks and benchmarks that
simulate real applications as well as possible, when running a whole application
is not feasible. Along a different axis, our benchmark collection originally
focused on the kinds of workloads seen by Googles Python code (webapps, text
processing), though we have since expanded the collection to include workloads
Google cares nothing about. We have so far shied away from heavily numerical
workloads, since NumPy <a class="footnote-reference brackets" href="#numpy" id="id34">[80]</a> already does an excellent job on such code and
so improving numerical performance was not an initial high priority for the
team; we have begun to incorporate such benchmarks into the collection
<a class="footnote-reference brackets" href="#us-nbody" id="id35">[97]</a> and have started work on optimizing numerical Python code.</p>
<p>Beyond these benchmarks, there are also a variety of workloads we are explicitly
not interested in benchmarking. Unladen Swallow is focused on improving the
performance of pure-Python code, so the performance of extension modules like
NumPy is uninteresting since NumPys core routines are implemented in
C. Similarly, workloads that involve a lot of IO like GUIs, databases or
socket-heavy applications would, we feel, fail to accurately measure interpreter
or code generation optimizations. That said, theres certainly room to improve
the performance of C-language extensions modules in the standard library, and
as such, we have added benchmarks for the <code class="docutils literal notranslate"><span class="pre">cPickle</span></code> and <code class="docutils literal notranslate"><span class="pre">re</span></code> modules.</p>
</section>
<section id="performance-vs-cpython-2-6-4">
<h3><a class="toc-backref" href="#performance-vs-cpython-2-6-4" role="doc-backlink">Performance vs CPython 2.6.4</a></h3>
<p>The charts below compare the arithmetic mean of multiple benchmark iterations
for CPython 2.6.4 and Unladen Swallow. <code class="docutils literal notranslate"><span class="pre">perf.py</span></code> gathers more data than this,
and indeed, arithmetic mean is not the whole story; we reproduce only the mean
for the sake of conciseness. We include the <code class="docutils literal notranslate"><span class="pre">t</span></code> score from the Students
two-tailed T-test <a class="footnote-reference brackets" href="#students-t-test" id="id36">[44]</a> at the 95% confidence interval to indicate
the significance of the result. Most benchmarks are run for 100 iterations,
though some longer-running whole-application benchmarks are run for fewer
iterations.</p>
<p>A description of each of these benchmarks is available on the Unladen Swallow
wiki <a class="footnote-reference brackets" href="#us-benchmarks" id="id37">[43]</a>.</p>
<p>Command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">./</span><span class="n">perf</span><span class="o">.</span><span class="n">py</span> <span class="o">-</span><span class="n">r</span> <span class="o">-</span><span class="n">b</span> <span class="n">default</span><span class="p">,</span><span class="n">apps</span> <span class="o">../</span><span class="n">a</span><span class="o">/</span><span class="n">python</span> <span class="o">../</span><span class="n">b</span><span class="o">/</span><span class="n">python</span>
</pre></div>
</div>
<p>32-bit; gcc 4.0.3; Ubuntu Dapper; Intel Core2 Duo 6600 &#64; 2.4GHz; 2 cores; 4MB L2 cache; 4GB RAM</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Benchmark</th>
<th class="head">CPython 2.6.4</th>
<th class="head">Unladen Swallow r988</th>
<th class="head">Change</th>
<th class="head">Significance</th>
<th class="head">Timeline</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>2to3</td>
<td>25.13 s</td>
<td>24.87 s</td>
<td>1.01x faster</td>
<td>t=8.94</td>
<td><a class="reference external" href="http://tinyurl.com/yamhrpg">http://tinyurl.com/yamhrpg</a></td>
</tr>
<tr class="row-odd"><td>django</td>
<td>1.08 s</td>
<td>0.80 s</td>
<td>1.35x faster</td>
<td>t=315.59</td>
<td><a class="reference external" href="http://tinyurl.com/y9mrn8s">http://tinyurl.com/y9mrn8s</a></td>
</tr>
<tr class="row-even"><td>html5lib</td>
<td>14.29 s</td>
<td>13.20 s</td>
<td>1.08x faster</td>
<td>t=2.17</td>
<td><a class="reference external" href="http://tinyurl.com/y8tyslu">http://tinyurl.com/y8tyslu</a></td>
</tr>
<tr class="row-odd"><td>nbody</td>
<td>0.51 s</td>
<td>0.28 s</td>
<td>1.84x faster</td>
<td>t=78.007</td>
<td><a class="reference external" href="http://tinyurl.com/y989qhg">http://tinyurl.com/y989qhg</a></td>
</tr>
<tr class="row-even"><td>rietveld</td>
<td>0.75 s</td>
<td>0.55 s</td>
<td>1.37x faster</td>
<td>Insignificant</td>
<td><a class="reference external" href="http://tinyurl.com/ye7mqd3">http://tinyurl.com/ye7mqd3</a></td>
</tr>
<tr class="row-odd"><td>slowpickle</td>
<td>0.75 s</td>
<td>0.55 s</td>
<td>1.37x faster</td>
<td>t=20.78</td>
<td><a class="reference external" href="http://tinyurl.com/ybrsfnd">http://tinyurl.com/ybrsfnd</a></td>
</tr>
<tr class="row-even"><td>slowspitfire</td>
<td>0.83 s</td>
<td>0.61 s</td>
<td>1.36x faster</td>
<td>t=2124.66</td>
<td><a class="reference external" href="http://tinyurl.com/yfknhaw">http://tinyurl.com/yfknhaw</a></td>
</tr>
<tr class="row-odd"><td>slowunpickle</td>
<td>0.33 s</td>
<td>0.26 s</td>
<td>1.26x faster</td>
<td>t=15.12</td>
<td><a class="reference external" href="http://tinyurl.com/yzlakoo">http://tinyurl.com/yzlakoo</a></td>
</tr>
<tr class="row-even"><td>spambayes</td>
<td>0.31 s</td>
<td>0.34 s</td>
<td>1.10x slower</td>
<td>Insignificant</td>
<td><a class="reference external" href="http://tinyurl.com/yem62ub">http://tinyurl.com/yem62ub</a></td>
</tr>
</tbody>
</table>
<p>64-bit; gcc 4.2.4; Ubuntu Hardy; AMD Opteron 8214 HE &#64; 2.2 GHz; 4 cores; 1MB L2 cache; 8GB RAM</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Benchmark</th>
<th class="head">CPython 2.6.4</th>
<th class="head">Unladen Swallow r988</th>
<th class="head">Change</th>
<th class="head">Significance</th>
<th class="head">Timeline</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>2to3</td>
<td>31.98 s</td>
<td>30.41 s</td>
<td>1.05x faster</td>
<td>t=8.35</td>
<td><a class="reference external" href="http://tinyurl.com/ybcrl3b">http://tinyurl.com/ybcrl3b</a></td>
</tr>
<tr class="row-odd"><td>django</td>
<td>1.22 s</td>
<td>0.94 s</td>
<td>1.30x faster</td>
<td>t=106.68</td>
<td><a class="reference external" href="http://tinyurl.com/ybwqll6">http://tinyurl.com/ybwqll6</a></td>
</tr>
<tr class="row-even"><td>html5lib</td>
<td>18.97 s</td>
<td>17.79 s</td>
<td>1.06x faster</td>
<td>t=2.78</td>
<td><a class="reference external" href="http://tinyurl.com/yzlyqvk">http://tinyurl.com/yzlyqvk</a></td>
</tr>
<tr class="row-odd"><td>nbody</td>
<td>0.77 s</td>
<td>0.27 s</td>
<td>2.86x faster</td>
<td>t=133.49</td>
<td><a class="reference external" href="http://tinyurl.com/yeyqhbg">http://tinyurl.com/yeyqhbg</a></td>
</tr>
<tr class="row-even"><td>rietveld</td>
<td>0.74 s</td>
<td>0.80 s</td>
<td>1.08x slower</td>
<td>t=-2.45</td>
<td><a class="reference external" href="http://tinyurl.com/yzjc6ff">http://tinyurl.com/yzjc6ff</a></td>
</tr>
<tr class="row-odd"><td>slowpickle</td>
<td>0.91 s</td>
<td>0.62 s</td>
<td>1.48x faster</td>
<td>t=28.04</td>
<td><a class="reference external" href="http://tinyurl.com/yf7en6k">http://tinyurl.com/yf7en6k</a></td>
</tr>
<tr class="row-even"><td>slowspitfire</td>
<td>1.01 s</td>
<td>0.72 s</td>
<td>1.40x faster</td>
<td>t=98.70</td>
<td><a class="reference external" href="http://tinyurl.com/yc8pe2o">http://tinyurl.com/yc8pe2o</a></td>
</tr>
<tr class="row-odd"><td>slowunpickle</td>
<td>0.51 s</td>
<td>0.34 s</td>
<td>1.51x faster</td>
<td>t=32.65</td>
<td><a class="reference external" href="http://tinyurl.com/yjufu4j">http://tinyurl.com/yjufu4j</a></td>
</tr>
<tr class="row-even"><td>spambayes</td>
<td>0.43 s</td>
<td>0.45 s</td>
<td>1.06x slower</td>
<td>Insignificant</td>
<td><a class="reference external" href="http://tinyurl.com/yztbjfp">http://tinyurl.com/yztbjfp</a></td>
</tr>
</tbody>
</table>
<p>Many of these benchmarks take a hit under Unladen Swallow because the current
version blocks execution to compile Python functions down to machine code. This
leads to the behaviour seen in the timeline graphs for the <code class="docutils literal notranslate"><span class="pre">html5lib</span></code> and
<code class="docutils literal notranslate"><span class="pre">rietveld</span></code> benchmarks, for example, and slows down the overall performance of
<code class="docutils literal notranslate"><span class="pre">2to3</span></code>. We have an active development branch to fix this problem
(<a class="footnote-reference brackets" href="#us-background-thread" id="id38">[46]</a>, <a class="footnote-reference brackets" href="#us-background-thread-issue" id="id39">[47]</a>), but working within
the strictures of CPythons current threading system has complicated the process
and required far more care and time than originally anticipated. We view this
issue as critical to final merger into the <code class="docutils literal notranslate"><span class="pre">py3k</span></code> branch.</p>
<p>We have obviously not met our initial goal of a 5x performance improvement. A
<a class="reference internal" href="#performance-retrospective">performance retrospective</a> follows, which addresses why we failed to meet our
initial performance goal. We maintain a list of yet-to-be-implemented
performance work <a class="footnote-reference brackets" href="#us-perf-punchlist" id="id40">[50]</a>.</p>
</section>
<section id="memory-usage">
<h3><a class="toc-backref" href="#memory-usage" role="doc-backlink">Memory Usage</a></h3>
<p>The following table shows maximum memory usage (in kilobytes) for each of
Unladen Swallows default benchmarks for both CPython 2.6.4 and Unladen Swallow
r988, as well as a timeline of memory usage across the lifetime of the
benchmark. We include tables for both 32- and 64-bit binaries. Memory usage was
measured on Linux 2.6 systems by summing the <code class="docutils literal notranslate"><span class="pre">Private_</span></code> sections from the
kernels <code class="docutils literal notranslate"><span class="pre">/proc/$pid/smaps</span></code> pseudo-files <a class="footnote-reference brackets" href="#smaps" id="id41">[45]</a>.</p>
<p>Command:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">./</span><span class="n">perf</span><span class="o">.</span><span class="n">py</span> <span class="o">-</span><span class="n">r</span> <span class="o">--</span><span class="n">track_memory</span> <span class="o">-</span><span class="n">b</span> <span class="n">default</span><span class="p">,</span><span class="n">apps</span> <span class="o">../</span><span class="n">a</span><span class="o">/</span><span class="n">python</span> <span class="o">../</span><span class="n">b</span><span class="o">/</span><span class="n">python</span>
</pre></div>
</div>
<p>32-bit</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Benchmark</th>
<th class="head">CPython 2.6.4</th>
<th class="head">Unladen Swallow r988</th>
<th class="head">Change</th>
<th class="head">Timeline</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>2to3</td>
<td>26396 kb</td>
<td>46896 kb</td>
<td>1.77x</td>
<td><a class="reference external" href="http://tinyurl.com/yhr2h4z">http://tinyurl.com/yhr2h4z</a></td>
</tr>
<tr class="row-odd"><td>django</td>
<td>10028 kb</td>
<td>27740 kb</td>
<td>2.76x</td>
<td><a class="reference external" href="http://tinyurl.com/yhan8vs">http://tinyurl.com/yhan8vs</a></td>
</tr>
<tr class="row-even"><td>html5lib</td>
<td>150028 kb</td>
<td>173924 kb</td>
<td>1.15x</td>
<td><a class="reference external" href="http://tinyurl.com/ybt44en">http://tinyurl.com/ybt44en</a></td>
</tr>
<tr class="row-odd"><td>nbody</td>
<td>3020 kb</td>
<td>16036 kb</td>
<td>5.31x</td>
<td><a class="reference external" href="http://tinyurl.com/ya8hltw">http://tinyurl.com/ya8hltw</a></td>
</tr>
<tr class="row-even"><td>rietveld</td>
<td>15008 kb</td>
<td>46400 kb</td>
<td>3.09x</td>
<td><a class="reference external" href="http://tinyurl.com/yhd5dra">http://tinyurl.com/yhd5dra</a></td>
</tr>
<tr class="row-odd"><td>slowpickle</td>
<td>4608 kb</td>
<td>16656 kb</td>
<td>3.61x</td>
<td><a class="reference external" href="http://tinyurl.com/ybukyvo">http://tinyurl.com/ybukyvo</a></td>
</tr>
<tr class="row-even"><td>slowspitfire</td>
<td>85776 kb</td>
<td>97620 kb</td>
<td>1.13x</td>
<td><a class="reference external" href="http://tinyurl.com/y9vj35z">http://tinyurl.com/y9vj35z</a></td>
</tr>
<tr class="row-odd"><td>slowunpickle</td>
<td>3448 kb</td>
<td>13744 kb</td>
<td>3.98x</td>
<td><a class="reference external" href="http://tinyurl.com/yexh4d5">http://tinyurl.com/yexh4d5</a></td>
</tr>
<tr class="row-even"><td>spambayes</td>
<td>7352 kb</td>
<td>46480 kb</td>
<td>6.32x</td>
<td><a class="reference external" href="http://tinyurl.com/yem62ub">http://tinyurl.com/yem62ub</a></td>
</tr>
</tbody>
</table>
<p>64-bit</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Benchmark</th>
<th class="head">CPython 2.6.4</th>
<th class="head">Unladen Swallow r988</th>
<th class="head">Change</th>
<th class="head">Timeline</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>2to3</td>
<td>51596 kb</td>
<td>82340 kb</td>
<td>1.59x</td>
<td><a class="reference external" href="http://tinyurl.com/yljg6rs">http://tinyurl.com/yljg6rs</a></td>
</tr>
<tr class="row-odd"><td>django</td>
<td>16020 kb</td>
<td>38908 kb</td>
<td>2.43x</td>
<td><a class="reference external" href="http://tinyurl.com/ylqsebh">http://tinyurl.com/ylqsebh</a></td>
</tr>
<tr class="row-even"><td>html5lib</td>
<td>259232 kb</td>
<td>324968 kb</td>
<td>1.25x</td>
<td><a class="reference external" href="http://tinyurl.com/yha6oee">http://tinyurl.com/yha6oee</a></td>
</tr>
<tr class="row-odd"><td>nbody</td>
<td>4296 kb</td>
<td>23012 kb</td>
<td>5.35x</td>
<td><a class="reference external" href="http://tinyurl.com/yztozza">http://tinyurl.com/yztozza</a></td>
</tr>
<tr class="row-even"><td>rietveld</td>
<td>24140 kb</td>
<td>73960 kb</td>
<td>3.06x</td>
<td><a class="reference external" href="http://tinyurl.com/ybg2nq7">http://tinyurl.com/ybg2nq7</a></td>
</tr>
<tr class="row-odd"><td>slowpickle</td>
<td>4928 kb</td>
<td>23300 kb</td>
<td>4.73x</td>
<td><a class="reference external" href="http://tinyurl.com/yk5tpbr">http://tinyurl.com/yk5tpbr</a></td>
</tr>
<tr class="row-even"><td>slowspitfire</td>
<td>133276 kb</td>
<td>148676 kb</td>
<td>1.11x</td>
<td><a class="reference external" href="http://tinyurl.com/y8bz2xe">http://tinyurl.com/y8bz2xe</a></td>
</tr>
<tr class="row-odd"><td>slowunpickle</td>
<td>4896 kb</td>
<td>16948 kb</td>
<td>3.46x</td>
<td><a class="reference external" href="http://tinyurl.com/ygywwoc">http://tinyurl.com/ygywwoc</a></td>
</tr>
<tr class="row-even"><td>spambayes</td>
<td>10728 kb</td>
<td>84992 kb</td>
<td>7.92x</td>
<td><a class="reference external" href="http://tinyurl.com/yhjban5">http://tinyurl.com/yhjban5</a></td>
</tr>
</tbody>
</table>
<p>The increased memory usage comes from a) LLVM code generation, analysis and
optimization libraries; b) native code; c) memory usage issues or leaks in
LLVM; d) data structures needed to optimize and generate machine code; e)
as-yet uncategorized other sources.</p>
<p>While we have made significant progress in reducing memory usage since the
initial naive JIT implementation <a class="footnote-reference brackets" href="#us-memory-issue" id="id42">[42]</a>, there is obviously more
to do. We believe that there are still memory savings to be made without
sacrificing performance. We have tended to focus on raw performance, and we
have not yet made a concerted push to reduce memory usage. We view reducing
memory usage as a blocking issue for final merger into the <code class="docutils literal notranslate"><span class="pre">py3k</span></code> branch. We
seek guidance from the community on an acceptable level of increased memory
usage.</p>
</section>
<section id="start-up-time">
<h3><a class="toc-backref" href="#start-up-time" role="doc-backlink">Start-up Time</a></h3>
<p>Statically linking LLVMs code generation, analysis and optimization libraries
increases the time needed to start the Python binary. C++ static initializers
used by LLVM also increase start-up time, as does importing the collection of
pre-compiled C runtime routines we want to inline to Python code.</p>
<p>Results from Unladen Swallows <code class="docutils literal notranslate"><span class="pre">startup</span></code> benchmarks:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ ./perf.py -r -b startup /tmp/cpy-26/bin/python /tmp/unladen/bin/python
### normal_startup ###
Min: 0.219186 -&gt; 0.352075: 1.6063x slower
Avg: 0.227228 -&gt; 0.364384: 1.6036x slower
Significant (t=-51.879098, a=0.95)
Stddev: 0.00762 -&gt; 0.02532: 3.3227x larger
Timeline: http://tinyurl.com/yfe8z3r
### startup_nosite ###
Min: 0.105949 -&gt; 0.264912: 2.5004x slower
Avg: 0.107574 -&gt; 0.267505: 2.4867x slower
Significant (t=-703.557403, a=0.95)
Stddev: 0.00214 -&gt; 0.00240: 1.1209x larger
Timeline: http://tinyurl.com/yajn8fa
### bzr_startup ###
Min: 0.067990 -&gt; 0.097985: 1.4412x slower
Avg: 0.084322 -&gt; 0.111348: 1.3205x slower
Significant (t=-37.432534, a=0.95)
Stddev: 0.00793 -&gt; 0.00643: 1.2330x smaller
Timeline: http://tinyurl.com/ybdm537
### hg_startup ###
Min: 0.016997 -&gt; 0.024997: 1.4707x slower
Avg: 0.026990 -&gt; 0.036772: 1.3625x slower
Significant (t=-53.104502, a=0.95)
Stddev: 0.00406 -&gt; 0.00417: 1.0273x larger
Timeline: http://tinyurl.com/ycout8m
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">bzr_startup</span></code> and <code class="docutils literal notranslate"><span class="pre">hg_startup</span></code> measure how long it takes Bazaar and
Mercurial, respectively, to display their help screens. <code class="docutils literal notranslate"><span class="pre">startup_nosite</span></code>
runs <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-S</span></code> many times; usage of the <code class="docutils literal notranslate"><span class="pre">-S</span></code> option is rare, but we feel
this gives a good indication of where increased startup time is coming from.</p>
<p>Unladen Swallow has made headway toward optimizing startup time, but there is
still more work to do and further optimizations to implement. Improving start-up
time is a high-priority item <a class="footnote-reference brackets" href="#us-issue-startup-time" id="id43">[33]</a> in Unladen Swallows
merger punchlist.</p>
</section>
<section id="binary-size">
<h3><a class="toc-backref" href="#binary-size" role="doc-backlink">Binary Size</a></h3>
<p>Statically linking LLVMs code generation, analysis and optimization libraries
significantly increases the size of the <code class="docutils literal notranslate"><span class="pre">python</span></code> binary. The tables below
report stripped on-disk binary sizes; the binaries are stripped to better
correspond with the configurations used by system package managers. We feel this
is the most realistic measure of any change in binary size.</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Binary size</th>
<th class="head">CPython 2.6.4</th>
<th class="head">CPython 3.1.1</th>
<th class="head">Unladen Swallow r1041</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>32-bit</td>
<td>1.3M</td>
<td>1.4M</td>
<td>12M</td>
</tr>
<tr class="row-odd"><td>64-bit</td>
<td>1.6M</td>
<td>1.6M</td>
<td>12M</td>
</tr>
</tbody>
</table>
<p>The increased binary size is caused by statically linking LLVMs code
generation, analysis and optimization libraries into the <code class="docutils literal notranslate"><span class="pre">python</span></code> binary.
This can be straightforwardly addressed by modifying LLVM to better support
shared linking and then using that, instead of the current static linking. For
the moment, though, static linking provides an accurate look at the cost of
linking against LLVM.</p>
<p>Even when statically linking, we believe there is still headroom to improve
on-disk binary size by narrowing Unladen Swallows dependencies on LLVM. This
issue is actively being addressed <a class="footnote-reference brackets" href="#us-binary-size" id="id44">[32]</a>.</p>
</section>
<section id="performance-retrospective">
<h3><a class="toc-backref" href="#performance-retrospective" role="doc-backlink">Performance Retrospective</a></h3>
<p>Our initial goal for Unladen Swallow was a 5x performance improvement over
CPython 2.6. We did not hit that, nor to put it bluntly, even come close. Why
did the project not hit that goal, and can an LLVM-based JIT ever hit that goal?</p>
<p>Why did Unladen Swallow not achieve its 5x goal? The primary reason was
that LLVM required more work than we had initially anticipated. Based on the
fact that Apple was shipping products based on LLVM <a class="footnote-reference brackets" href="#llvm-users" id="id45">[82]</a>, and
other high-level languages had successfully implemented LLVM-based JITs
(<a class="footnote-reference brackets" href="#rubinius" id="id46">[61]</a>, <a class="footnote-reference brackets" href="#macruby" id="id47">[63]</a>, <a class="footnote-reference brackets" href="#hlvm" id="id48">[83]</a>), we had assumed that LLVMs JIT was
relatively free of show-stopper bugs.</p>
<p>That turned out to be incorrect. We had to turn our attention away from
performance to fix a number of critical bugs in LLVMs JIT infrastructure (for
example, <a class="footnote-reference brackets" href="#llvm-far-call-issue" id="id49">[84]</a>, <a class="footnote-reference brackets" href="#llvm-jmm-rev" id="id50">[85]</a>) as well as a number of
nice-to-have enhancements that would enable further optimizations along various
axes (for example, <a class="footnote-reference brackets" href="#llvm-globaldce-rev" id="id51">[87]</a>,
<a class="footnote-reference brackets" href="#llvm-memleak-rev" id="id52">[86]</a>, <a class="footnote-reference brackets" href="#llvm-availext-issue" id="id53">[88]</a>). LLVMs static code generation
facilities, tools and optimization passes are stable and stress-tested, but the
just-in-time infrastructure was relatively untested and buggy. We have fixed
this.</p>
<p>(Our hypothesis is that we hit these problems problems other projects had
avoided because of the complexity and thoroughness of CPythons standard
library test suite.)</p>
<p>We also diverted engineering effort away from performance and into support tools
such as gdb and oProfile. gdb did not work well with JIT compilers at all, and
LLVM previously had no integration with oProfile. Having JIT-aware debuggers and
profilers has been very valuable to the project, and we do not regret
channeling our time in these directions. See the <a class="reference internal" href="#debugging">Debugging</a> and <a class="reference internal" href="#profiling">Profiling</a>
sections for more information.</p>
<p>Can an LLVM-based CPython JIT ever hit the 5x performance target? The benchmark
results for JIT-based JavaScript implementations suggest that 5x is indeed
possible, as do the results PyPys JIT has delivered for numeric workloads. The
experience of Self-92 <a class="footnote-reference brackets" href="#urs-self" id="id54">[52]</a> is also instructive.</p>
<p>Can LLVM deliver this? We believe that we have only begun to scratch the surface
of what our LLVM-based JIT can deliver. The optimizations we have incorporated
into this system thus far have borne significant fruit (for example,
<a class="footnote-reference brackets" href="#us-specialization-issue" id="id55">[89]</a>, <a class="footnote-reference brackets" href="#us-direct-calling-issue" id="id56">[90]</a>,
<a class="footnote-reference brackets" href="#us-fast-globals-issue" id="id57">[91]</a>). Our experience to date is that the limiting factor
on Unladen Swallows performance is the engineering cycles needed to implement
the literature. We have found LLVM easy to work with and to modify, and its
built-in optimizations have greatly simplified the task of implementing
Python-level optimizations.</p>
<p>An overview of further performance opportunities is discussed in the
<a class="reference internal" href="#future-work">Future Work</a> section.</p>
</section>
</section>
<section id="correctness-and-compatibility">
<h2><a class="toc-backref" href="#correctness-and-compatibility" role="doc-backlink">Correctness and Compatibility</a></h2>
<p>Unladen Swallows correctness test suite includes CPythons test suite (under
<code class="docutils literal notranslate"><span class="pre">Lib/test/</span></code>), as well as a number of important third-party applications and
libraries <a class="footnote-reference brackets" href="#tested-apps" id="id58">[6]</a>. A full list of these applications and libraries is
reproduced below. Any dependencies needed by these packages, such as
<code class="docutils literal notranslate"><span class="pre">zope.interface</span></code> <a class="footnote-reference brackets" href="#zope-interface" id="id59">[34]</a>, are also tested indirectly as a part of
testing the primary package, thus widening the corpus of tested third-party
Python code.</p>
<ul class="simple">
<li>2to3</li>
<li>Cheetah</li>
<li>cvs2svn</li>
<li>Django</li>
<li>Nose</li>
<li>NumPy</li>
<li>PyCrypto</li>
<li>pyOpenSSL</li>
<li>PyXML</li>
<li>Setuptools</li>
<li>SQLAlchemy</li>
<li>SWIG</li>
<li>SymPy</li>
<li>Twisted</li>
<li>ZODB</li>
</ul>
<p>These applications pass all relevant tests when run under Unladen Swallow. Note
that some tests that failed against our baseline of CPython 2.6.4 were disabled,
as were tests that made assumptions about CPython internals such as exact
bytecode numbers or bytecode format. Any package with disabled tests includes
a <code class="docutils literal notranslate"><span class="pre">README.unladen</span></code> file that details the changes (for example,
<a class="footnote-reference brackets" href="#us-sqlalchemy-readme" id="id60">[37]</a>).</p>
<p>In addition, Unladen Swallow is tested automatically against an array of
internal Google Python libraries and applications. These include Googles
internal Python bindings for BigTable <a class="footnote-reference brackets" href="#bigtable" id="id61">[35]</a>, the Mondrian code review
application <a class="footnote-reference brackets" href="#mondrian" id="id62">[36]</a>, and Googles Python standard library, among others.
The changes needed to run these projects under Unladen Swallow have consistently
broken into one of three camps:</p>
<ul class="simple">
<li>Adding CPython 2.6 C API compatibility. Since Google still primarily uses
CPython 2.4 internally, we have needed to convert uses of <code class="docutils literal notranslate"><span class="pre">int</span></code> to
<code class="docutils literal notranslate"><span class="pre">Py_ssize_t</span></code> and similar API changes.</li>
<li>Fixing or disabling explicit, incorrect tests of the CPython version number.</li>
<li>Conditionally disabling code that worked around or depending on bugs in
CPython 2.4 that have since been fixed.</li>
</ul>
<p>Testing against this wide range of public and proprietary applications and
libraries has been instrumental in ensuring the correctness of Unladen Swallow.
Testing has exposed bugs that we have duly corrected. Our automated regression
testing regime has given us high confidence in our changes as we have moved
forward.</p>
<p>In addition to third-party testing, we have added further tests to CPythons
test suite for corner cases of the language or implementation that we felt were
untested or underspecified (for example, <a class="footnote-reference brackets" href="#us-import-tests" id="id63">[48]</a>,
<a class="footnote-reference brackets" href="#us-tracing-tests" id="id64">[49]</a>). These have been especially important when implementing
optimizations, helping make sure we have not accidentally broken the darker
corners of Python.</p>
<p>We have also constructed a test suite focused solely on the LLVM-based JIT
compiler and the optimizations implemented for it <a class="footnote-reference brackets" href="#us-test-llvm" id="id65">[38]</a>. Because of
the complexity and subtlety inherent in writing an optimizing compiler, we have
attempted to exhaustively enumerate the constructs, scenarios and corner cases
we are compiling and optimizing. The JIT tests also include tests for things
like the JIT hotness model, making it easier for future CPython developers to
maintain and improve.</p>
<p>We have recently begun using fuzz testing <a class="footnote-reference brackets" href="#fuzz-testing" id="id66">[39]</a> to stress-test the
compiler. We have used both pyfuzz <a class="footnote-reference brackets" href="#pyfuzz" id="id67">[40]</a> and Fusil <a class="footnote-reference brackets" href="#fusil" id="id68">[41]</a> in the past,
and we recommend they be introduced as an automated part of the CPython testing
process.</p>
<section id="known-incompatibilities">
<h3><a class="toc-backref" href="#known-incompatibilities" role="doc-backlink">Known Incompatibilities</a></h3>
<p>The only application or library we know to not work with Unladen Swallow that
does work with CPython 2.6.4 is Psyco <a class="footnote-reference brackets" href="#psyco" id="id69">[65]</a>. We are aware of some libraries
such as PyGame <a class="footnote-reference brackets" href="#pygame" id="id70">[79]</a> that work well with CPython 2.6.4, but suffer some
degradation due to changes made in Unladen Swallow. We are tracking this issue
<a class="footnote-reference brackets" href="#us-background-thread-issue" id="id71">[47]</a> and are working to resolve these instances of
degradation.</p>
<p>While Unladen Swallow is source-compatible with CPython 2.6.4, it is not
binary compatible. C extension modules compiled against one will need to be
recompiled to work with the other.</p>
<p>The merger of Unladen Swallow should have minimal impact on long-lived
CPython optimization branches like WPython. WPython <a class="footnote-reference brackets" href="#wpython" id="id72">[105]</a> and Unladen
Swallow are largely orthogonal, and there is no technical reason why both
could not be merged into CPython. The changes needed to make WPython
compatible with a JIT-enhanced version of CPython should be minimal
<a class="footnote-reference brackets" href="#us-wpython-compat" id="id73">[114]</a>. The same should be true for other CPython optimization
projects (for example, <a class="footnote-reference brackets" href="#asher-rotem" id="id74">[115]</a>).</p>
<p>Invasive forks of CPython such as Stackless Python <a class="footnote-reference brackets" href="#stackless" id="id75">[116]</a> are more
challenging to support. Since Stackless is highly unlikely to be merged into
CPython <a class="footnote-reference brackets" href="#stackless-merger" id="id76">[117]</a> and an increased maintenance burden is part and
parcel of any fork, we consider compatibility with Stackless to be relatively
low-priority. JIT-compiled stack frames use the C stack, so Stackless should
be able to treat them the same as it treats calls through extension modules.
If that turns out to be unacceptable, Stackless could either remove the JIT
compiler or improve JIT code generation to better support heap-based stack
frames <a class="footnote-reference brackets" href="#llvm-heap-frames" id="id77">[118]</a>, <a class="footnote-reference brackets" href="#llvm-heap-frames-disc" id="id78">[119]</a>.</p>
</section>
</section>
<section id="platform-support">
<h2><a class="toc-backref" href="#platform-support" role="doc-backlink">Platform Support</a></h2>
<p>Unladen Swallow is inherently limited by the platform support provided by LLVM,
especially LLVMs JIT compilation system <a class="footnote-reference brackets" href="#llvm-hardware" id="id79">[7]</a>. LLVMs JIT has the
best support on x86 and x86-64 systems, and these are the platforms where
Unladen Swallow has received the most testing. We are confident in LLVM/Unladen
Swallows support for x86 and x86-64 hardware. PPC and ARM support exists, but
is not widely used and may be buggy (for example, <a class="footnote-reference brackets" href="#llvm-ppc-eager-jit-issue" id="id80">[100]</a>,
<a class="footnote-reference brackets" href="#llvm-far-call-issue" id="id81">[84]</a>, <a class="footnote-reference brackets" href="#llvm-arm-jit-issue" id="id82">[101]</a>).</p>
<p>Unladen Swallow is known to work on the following operating systems: Linux,
Darwin, Windows. Unladen Swallow has received the most testing on Linux and
Darwin, though it still builds and passes its tests on Windows.</p>
<p>In order to support hardware and software platforms where LLVMs JIT does not
work, Unladen Swallow provides a <code class="docutils literal notranslate"><span class="pre">./configure</span> <span class="pre">--without-llvm</span></code> option. This
flag carves out any part of Unladen Swallow that depends on LLVM, yielding a
Python binary that works and passes its tests, but has no performance
advantages. This configuration is recommended for hardware unsupported by LLVM,
or systems that care more about memory usage than performance.</p>
</section>
<section id="impact-on-cpython-development">
<h2><a class="toc-backref" href="#impact-on-cpython-development" role="doc-backlink">Impact on CPython Development</a></h2>
<section id="experimenting-with-changes-to-python-or-cpython-bytecode">
<h3><a class="toc-backref" href="#experimenting-with-changes-to-python-or-cpython-bytecode" role="doc-backlink">Experimenting with Changes to Python or CPython Bytecode</a></h3>
<p>Unladen Swallows JIT compiler operates on CPython bytecode, and as such, it is
immune to Python language changes that affect only the parser.</p>
<p>We recommend that changes to the CPython bytecode compiler or the semantics of
individual bytecodes be prototyped in the interpreter loop first, then be ported
to the JIT compiler once the semantics are clear. To make this easier, Unladen
Swallow includes a <code class="docutils literal notranslate"><span class="pre">--without-llvm</span></code> configure-time option that strips out the
JIT compiler and all associated infrastructure. This leaves the current burden
of experimentation unchanged so that developers can prototype in the current
low-barrier-to-entry interpreter loop.</p>
<p>Unladen Swallow began implementing its JIT compiler by doing straightforward,
naive translations from bytecode implementations into LLVM API calls. We found
this process to be easily understood, and we recommend the same approach for
CPython. We include several sample changes from the Unladen Swallow repository
here as examples of this style of development: <a class="footnote-reference brackets" href="#us-r359" id="id83">[26]</a>, <a class="footnote-reference brackets" href="#us-r376" id="id84">[27]</a>,
<a class="footnote-reference brackets" href="#us-r417" id="id85">[28]</a>, <a class="footnote-reference brackets" href="#us-r517" id="id86">[29]</a>.</p>
</section>
<section id="debugging">
<h3><a class="toc-backref" href="#debugging" role="doc-backlink">Debugging</a></h3>
<p>The Unladen Swallow team implemented changes to gdb to make it easier to use gdb
to debug JIT-compiled Python code. These changes were released in gdb 7.0
<a class="footnote-reference brackets" href="#gdb70" id="id87">[17]</a>. They make it possible for gdb to identify and unwind past
JIT-generated call stack frames. This allows gdb to continue to function as
before for CPython development if one is changing, for example, the <code class="docutils literal notranslate"><span class="pre">list</span></code>
type or builtin functions.</p>
<p>Example backtrace after our changes, where <code class="docutils literal notranslate"><span class="pre">baz</span></code>, <code class="docutils literal notranslate"><span class="pre">bar</span></code> and <code class="docutils literal notranslate"><span class="pre">foo</span></code> are
JIT-compiled:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Program</span> <span class="n">received</span> <span class="n">signal</span> <span class="n">SIGSEGV</span><span class="p">,</span> <span class="n">Segmentation</span> <span class="n">fault</span><span class="o">.</span>
<span class="mh">0x00002aaaabe7d1a8</span> <span class="ow">in</span> <span class="n">baz</span> <span class="p">()</span>
<span class="p">(</span><span class="n">gdb</span><span class="p">)</span> <span class="n">bt</span>
<span class="c1">#0 0x00002aaaabe7d1a8 in baz ()</span>
<span class="c1">#1 0x00002aaaabe7d12c in bar ()</span>
<span class="c1">#2 0x00002aaaabe7d0aa in foo ()</span>
<span class="c1">#3 0x00002aaaabe7d02c in main ()</span>
<span class="c1">#4 0x0000000000b870a2 in llvm::JIT::runFunction (this=0x1405b70, F=0x14024e0, ArgValues=...)</span>
<span class="n">at</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">rnk</span><span class="o">/</span><span class="n">llvm</span><span class="o">-</span><span class="n">gdb</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">ExecutionEngine</span><span class="o">/</span><span class="n">JIT</span><span class="o">/</span><span class="n">JIT</span><span class="o">.</span><span class="n">cpp</span><span class="p">:</span><span class="mi">395</span>
<span class="c1">#5 0x0000000000baa4c5 in llvm::ExecutionEngine::runFunctionAsMain</span>
<span class="p">(</span><span class="n">this</span><span class="o">=</span><span class="mh">0x1405b70</span><span class="p">,</span> <span class="n">Fn</span><span class="o">=</span><span class="mh">0x14024e0</span><span class="p">,</span> <span class="n">argv</span><span class="o">=...</span><span class="p">,</span> <span class="n">envp</span><span class="o">=</span><span class="mh">0x7fffffffe3c0</span><span class="p">)</span>
<span class="n">at</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">rnk</span><span class="o">/</span><span class="n">llvm</span><span class="o">-</span><span class="n">gdb</span><span class="o">/</span><span class="n">lib</span><span class="o">/</span><span class="n">ExecutionEngine</span><span class="o">/</span><span class="n">ExecutionEngine</span><span class="o">.</span><span class="n">cpp</span><span class="p">:</span><span class="mi">377</span>
<span class="c1">#6 0x00000000007ebd52 in main (argc=2, argv=0x7fffffffe3a8,</span>
<span class="n">envp</span><span class="o">=</span><span class="mh">0x7fffffffe3c0</span><span class="p">)</span> <span class="n">at</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">rnk</span><span class="o">/</span><span class="n">llvm</span><span class="o">-</span><span class="n">gdb</span><span class="o">/</span><span class="n">tools</span><span class="o">/</span><span class="n">lli</span><span class="o">/</span><span class="n">lli</span><span class="o">.</span><span class="n">cpp</span><span class="p">:</span><span class="mi">208</span>
</pre></div>
</div>
<p>Previously, the JIT-compiled frames would have caused gdb to unwind incorrectly,
generating lots of obviously-incorrect <code class="docutils literal notranslate"><span class="pre">#6</span> <span class="pre">0x00002aaaabe7d0aa</span> <span class="pre">in</span> <span class="pre">??</span> <span class="pre">()</span></code>-style
stack frames.</p>
<p>Highlights:</p>
<ul class="simple">
<li>gdb 7.0 is able to correctly parse JIT-compiled stack frames, allowing full
use of gdb on non-JIT-compiled functions, that is, the vast majority of the
CPython codebase.</li>
<li>Disassembling inside a JIT-compiled stack frame automatically prints the full
list of instructions making up that function. This is an advance over the
state of gdb before our work: developers needed to guess the starting address
of the function and manually disassemble the assembly code.</li>
<li>Flexible underlying mechanism allows CPython to add more and more information,
and eventually reach parity with C/C++ support in gdb for JIT-compiled machine
code.</li>
</ul>
<p>Lowlights:</p>
<ul class="simple">
<li>gdb cannot print local variables or tell you what line youre currently
executing inside a JIT-compiled function. Nor can it step through
JIT-compiled code, except for one instruction at a time.</li>
<li>Not yet integrated with Apples gdb or Microsofts Visual Studio debuggers.</li>
</ul>
<p>The Unladen Swallow team is working with Apple to get these changes
incorporated into their future gdb releases.</p>
</section>
<section id="profiling">
<h3><a class="toc-backref" href="#profiling" role="doc-backlink">Profiling</a></h3>
<p>Unladen Swallow integrates with oProfile 0.9.4 and newer <a class="footnote-reference brackets" href="#oprofile" id="id88">[18]</a> to support
assembly-level profiling on Linux systems. This means that oProfile will
correctly symbolize JIT-compiled functions in its reports.</p>
<p>Example report, where the <code class="docutils literal notranslate"><span class="pre">#u#</span></code>-prefixed symbol names are JIT-compiled Python
functions:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ opreport -l ./python | less
CPU: Core 2, speed 1600 MHz (estimated)
Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000
samples % image name symbol name
79589 4.2329 python PyString_FromFormatV
62971 3.3491 python PyEval_EvalCodeEx
62713 3.3354 python tupledealloc
57071 3.0353 python _PyEval_CallFunction
50009 2.6597 24532.jo #u#force_unicode
47468 2.5246 python PyUnicodeUCS2_Decode
45829 2.4374 python PyFrame_New
45173 2.4025 python lookdict_string
43082 2.2913 python PyType_IsSubtype
39763 2.1148 24532.jo #u#render5
38145 2.0287 python _PyType_Lookup
37643 2.0020 python PyObject_GC_UnTrack
37105 1.9734 python frame_dealloc
36849 1.9598 python PyEval_EvalFrame
35630 1.8950 24532.jo #u#resolve
33313 1.7717 python PyObject_IsInstance
33208 1.7662 python PyDict_GetItem
33168 1.7640 python PyTuple_New
30458 1.6199 python PyCFunction_NewEx
</pre></div>
</div>
<p>This support is functional, but as-yet unpolished. Unladen Swallow maintains a
punchlist of items we feel are important to improve in our oProfile integration
to make it more useful to core CPython developers <a class="footnote-reference brackets" href="#us-oprofile-punchlist" id="id89">[19]</a>.</p>
<p>Highlights:</p>
<ul class="simple">
<li>Symbolization of JITted frames working in oProfile on Linux.</li>
</ul>
<p>Lowlights:</p>
<ul class="simple">
<li>No work yet invested in improving symbolization of JIT-compiled frames for
Apples Shark <a class="footnote-reference brackets" href="#shark" id="id90">[20]</a> or Microsofts Visual Studio profiling tools.</li>
<li>Some polishing still desired for oProfile output.</li>
</ul>
<p>We recommend using oProfile 0.9.5 (and newer) to work around a now-fixed bug on
x86-64 platforms in oProfile. oProfile 0.9.4 will work fine on 32-bit platforms,
however.</p>
<p>Given the ease of integrating oProfile with LLVM <a class="footnote-reference brackets" href="#llvm-oprofile-change" id="id91">[21]</a> and
Unladen Swallow <a class="footnote-reference brackets" href="#us-oprofile-change" id="id92">[22]</a>, other profiling tools should be easy as
well, provided they support a similar JIT interface <a class="footnote-reference brackets" href="#oprofile-jit-interface" id="id93">[23]</a>.</p>
<p>We have documented the process for using oProfile to profile Unladen Swallow
<a class="footnote-reference brackets" href="#oprofile-workflow" id="id94">[24]</a>. This document will be merged into CPythons <code class="docutils literal notranslate"><span class="pre">Doc/</span></code>
tree in the merge.</p>
</section>
<section id="addition-of-c-to-cpython">
<h3><a class="toc-backref" href="#addition-of-c-to-cpython" role="doc-backlink">Addition of C++ to CPython</a></h3>
<p>In order to use LLVM, Unladen Swallow has introduced C++ into the core CPython
tree and build process. This is an unavoidable part of depending on LLVM; though
LLVM offers a C API <a class="footnote-reference brackets" href="#llvm-c-api" id="id95">[8]</a>, it is limited and does not expose the
functionality needed by CPython. Because of this, we have implemented the
internal details of the Unladen Swallow JIT and its supporting infrastructure
in C++. We do not propose converting the entire CPython codebase to C++.</p>
<p>Highlights:</p>
<ul class="simple">
<li>Easy use of LLVMs full, powerful code generation and related APIs.</li>
<li>Convenient, abstract data structures simplify code.</li>
<li>C++ is limited to relatively small corners of the CPython codebase.</li>
<li>C++ can be disabled via <code class="docutils literal notranslate"><span class="pre">./configure</span> <span class="pre">--without-llvm</span></code>, which even omits the
dependency on <code class="docutils literal notranslate"><span class="pre">libstdc++</span></code>.</li>
</ul>
<p>Lowlights:</p>
<ul class="simple">
<li>Developers must know two related languages, C and C++ to work on the full
range of CPythons internals.</li>
<li>A C++ style guide will need to be developed and enforced. <a class="pep reference internal" href="../pep-0007/" title="PEP 7 Style Guide for C Code">PEP 7</a> will be
extended <a class="footnote-reference brackets" href="#pep7-cpp" id="id96">[120]</a> to encompass C++ by taking the relevant parts of
the C++ style guides from Unladen Swallow <a class="footnote-reference brackets" href="#us-styleguide" id="id97">[70]</a>, LLVM
<a class="footnote-reference brackets" href="#llvm-styleguide" id="id98">[71]</a> and Google <a class="footnote-reference brackets" href="#google-styleguide" id="id99">[72]</a>.</li>
<li>Different C++ compilers emit different ABIs; this can cause problems if
CPython is compiled with one C++ compiler and extensions modules are compiled
with a different C++ compiler.</li>
</ul>
</section>
<section id="managing-llvm-releases-c-api-changes">
<h3><a class="toc-backref" href="#managing-llvm-releases-c-api-changes" role="doc-backlink">Managing LLVM Releases, C++ API Changes</a></h3>
<p>LLVM is released regularly every six months. This means that LLVM may be
released two or three times during the course of development of a CPython 3.x
release. Each LLVM release brings newer and more powerful optimizations,
improved platform support and more sophisticated code generation.</p>
<p>LLVM releases usually include incompatible changes to the LLVM C++ API; the
release notes for LLVM 2.6 <a class="footnote-reference brackets" href="#llvm-26-whatsnew" id="id100">[9]</a> include a list of
intentionally-introduced incompatibilities. Unladen Swallow has tracked LLVM
trunk closely over the course of development. Our experience has been
that LLVM API changes are obvious and easily or mechanically remedied. We
include two such changes from the Unladen Swallow tree as references here:
<a class="footnote-reference brackets" href="#us-llvm-r820" id="id101">[10]</a>, <a class="footnote-reference brackets" href="#us-llvm-r532" id="id102">[11]</a>.</p>
<p>Due to API incompatibilities, we recommend that an LLVM-based CPython target
compatibility with a single version of LLVM at a time. This will lower the
overhead on the core development team. Pegging to an LLVM version should not be
a problem from a packaging perspective, because pre-built LLVM packages
generally become available via standard system package managers fairly quickly
following an LLVM release, and failing that, llvm.org itself includes binary
releases.</p>
<p>Unladen Swallow has historically included a copy of the LLVM and Clang source
trees in the Unladen Swallow tree; this was done to allow us to closely track
LLVM trunk as we made patches to it. We do not recommend this model of
development for CPython. CPython releases should be based on official LLVM
releases. Pre-built LLVM packages are available from MacPorts <a class="footnote-reference brackets" href="#llvm-macports" id="id103">[12]</a>
for Darwin, and from most major Linux distributions (<a class="footnote-reference brackets" href="#llvm-ubuntu" id="id104">[13]</a>,
<a class="footnote-reference brackets" href="#llvm-debian" id="id105">[14]</a>, <a class="footnote-reference brackets" href="#llvm-fedora" id="id106">[16]</a>). LLVM itself provides additional binaries,
such as for MinGW <a class="footnote-reference brackets" href="#llvm-mingw" id="id107">[25]</a>.</p>
<p>LLVM is currently intended to be statically linked; this means that binary
releases of CPython will include the relevant parts (not all!) of LLVM. This
will increase the binary size, as noted above. To simplify downstream package
management, we will modify LLVM to better support shared linking. This issue
will block final merger <a class="footnote-reference brackets" href="#us-shared-link-issue" id="id108">[98]</a>.</p>
<p>Unladen Swallow has tasked a full-time engineer with fixing any remaining
critical issues in LLVM before LLVMs 2.7 release. We consider it essential that
CPython 3.x be able to depend on a released version of LLVM, rather than closely
tracking LLVM trunk as Unladen Swallow has done. We believe we will finish this
work <a class="footnote-reference brackets" href="#us-llvm-punchlist" id="id109">[99]</a> before the release of LLVM 2.7, expected in May 2010.</p>
</section>
<section id="building-cpython">
<h3><a class="toc-backref" href="#building-cpython" role="doc-backlink">Building CPython</a></h3>
<p>In addition to a runtime dependency on LLVM, Unladen Swallow includes a
build-time dependency on Clang <a class="footnote-reference brackets" href="#clang" id="id110">[5]</a>, an LLVM-based C/C++ compiler. We use
this to compile parts of the C-language Python runtime to LLVMs intermediate
representation; this allows us to perform cross-language inlining, yielding
increased performance. Clang is not required to run Unladen Swallow. Clang
binary packages are available from most major Linux distributions (for example,
<a class="footnote-reference brackets" href="#clang-debian" id="id111">[15]</a>).</p>
<p>We examined the impact of Unladen Swallow on the time needed to build Python,
including configure, full builds and incremental builds after touching a single
C source file.</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">./configure</th>
<th class="head">CPython 2.6.4</th>
<th class="head">CPython 3.1.1</th>
<th class="head">Unladen Swallow r988</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>Run 1</td>
<td>0m20.795s</td>
<td>0m16.558s</td>
<td>0m15.477s</td>
</tr>
<tr class="row-odd"><td>Run 2</td>
<td>0m15.255s</td>
<td>0m16.349s</td>
<td>0m15.391s</td>
</tr>
<tr class="row-even"><td>Run 3</td>
<td>0m15.228s</td>
<td>0m16.299s</td>
<td>0m15.528s</td>
</tr>
</tbody>
</table>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Full make</th>
<th class="head">CPython 2.6.4</th>
<th class="head">CPython 3.1.1</th>
<th class="head">Unladen Swallow r988</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>Run 1</td>
<td>1m30.776s</td>
<td>1m22.367s</td>
<td>1m54.053s</td>
</tr>
<tr class="row-odd"><td>Run 2</td>
<td>1m21.374s</td>
<td>1m22.064s</td>
<td>1m49.448s</td>
</tr>
<tr class="row-even"><td>Run 3</td>
<td>1m22.047s</td>
<td>1m23.645s</td>
<td>1m49.305s</td>
</tr>
</tbody>
</table>
<p>Full builds take a hit due to a) additional <code class="docutils literal notranslate"><span class="pre">.cc</span></code> files needed for LLVM
interaction, b) statically linking LLVM into <code class="docutils literal notranslate"><span class="pre">libpython</span></code>, c) compiling parts
of the Python runtime to LLVM IR to enable cross-language inlining.</p>
<p>Incremental builds are also somewhat slower than mainline CPython. The table
below shows incremental rebuild times after touching <code class="docutils literal notranslate"><span class="pre">Objects/listobject.c</span></code>.</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head">Incr make</th>
<th class="head">CPython 2.6.4</th>
<th class="head">CPython 3.1.1</th>
<th class="head">Unladen Swallow r1024</th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td>Run 1</td>
<td>0m1.854s</td>
<td>0m1.456s</td>
<td>0m6.680s</td>
</tr>
<tr class="row-odd"><td>Run 2</td>
<td>0m1.437s</td>
<td>0m1.442s</td>
<td>0m5.310s</td>
</tr>
<tr class="row-even"><td>Run 3</td>
<td>0m1.440s</td>
<td>0m1.425s</td>
<td>0m7.639s</td>
</tr>
</tbody>
</table>
<p>As with full builds, this extra time comes from statically linking LLVM
into <code class="docutils literal notranslate"><span class="pre">libpython</span></code>. If <code class="docutils literal notranslate"><span class="pre">libpython</span></code> were linked shared against LLVM, this
overhead would go down.</p>
</section>
</section>
<section id="proposed-merge-plan">
<h2><a class="toc-backref" href="#proposed-merge-plan" role="doc-backlink">Proposed Merge Plan</a></h2>
<p>We propose focusing our efforts on eventual merger with CPythons 3.x line of
development. The BDFL has indicated that 2.7 is to be the final release of
CPythons 2.x line of development <a class="footnote-reference brackets" href="#bdfl-27-final" id="id112">[30]</a>, and since 2.7 alpha 1 has
<a class="pep reference internal" href="../pep-0373/" title="PEP 373 Python 2.7 Release Schedule">already been released</a>, we have missed the window. Python 3 is the
future, and that is where we will target our performance efforts.</p>
<p>We recommend the following plan for merger of Unladen Swallow into the CPython
source tree:</p>
<ul class="simple">
<li>Creation of a branch in the CPython SVN repository to work in, call it
<code class="docutils literal notranslate"><span class="pre">py3k-jit</span></code> as a strawman. This will be a branch of the CPython <code class="docutils literal notranslate"><span class="pre">py3k</span></code>
branch.</li>
<li>We will keep this branch closely integrated to <code class="docutils literal notranslate"><span class="pre">py3k</span></code>. The further we
deviate, the harder our work will be.</li>
<li>Any JIT-related patches will go into the <code class="docutils literal notranslate"><span class="pre">py3k-jit</span></code> branch.</li>
<li>Non-JIT-related patches will go into the <code class="docutils literal notranslate"><span class="pre">py3k</span></code> branch (once reviewed and
approved) and be merged back into the <code class="docutils literal notranslate"><span class="pre">py3k-jit</span></code> branch.</li>
<li>Potentially-contentious issues, such as the introduction of new command line
flags or environment variables, will be discussed on python-dev.</li>
</ul>
<p>Because Google uses CPython 2.x internally, Unladen Swallow is based on CPython
2.6. We would need to port our compiler to Python 3; this would be done as
patches are applied to the <code class="docutils literal notranslate"><span class="pre">py3k-jit</span></code> branch, so that the branch remains a
consistent implementation of Python 3 at all times.</p>
<p>We believe this approach will be minimally disruptive to the 3.2 or 3.3 release
process while we iron out any remaining issues blocking final merger into
<code class="docutils literal notranslate"><span class="pre">py3k</span></code>. Unladen Swallow maintains a punchlist of known issues needed before
final merger <a class="footnote-reference brackets" href="#us-punchlist" id="id113">[31]</a>, which includes all problems mentioned in this
PEP; we trust the CPython community will have its own concerns. This punchlist
is not static; other issues may emerge in the future that will block final
merger into the <code class="docutils literal notranslate"><span class="pre">py3k</span></code> branch.</p>
<p>Changes will be committed directly to the <code class="docutils literal notranslate"><span class="pre">py3k-jit</span></code> branch, with only large,
tricky or controversial changes sent for pre-commit code review.</p>
<section id="contingency-plans">
<h3><a class="toc-backref" href="#contingency-plans" role="doc-backlink">Contingency Plans</a></h3>
<p>There is a chance that we will not be able to reduce memory usage or startup
time to a level satisfactory to the CPython community. Our primary contingency
plan for this situation is to shift from an online just-in-time compilation
strategy to an offline ahead-of-time strategy using an instrumented CPython
interpreter loop to obtain feedback. This is the same model used by gccs
feedback-directed optimizations (<cite>-fprofile-generate</cite>) <a class="footnote-reference brackets" href="#gcc-fdo" id="id114">[112]</a> and
Microsoft Visual Studios profile-guided optimizations <a class="footnote-reference brackets" href="#msvc-pgo" id="id115">[113]</a>; we will
refer to this as “feedback-directed optimization” here, or FDO.</p>
<p>We believe that an FDO compiler for Python would be inferior to a JIT compiler.
FDO requires a high-quality, representative benchmark suite, which is a relative
rarity in both open- and closed-source development. A JIT compiler can
dynamically find and optimize the hot spots in any application benchmark
suite or no allowing it to adapt to changes in application bottlenecks
without human intervention.</p>
<p>If an ahead-of-time FDO compiler is required, it should be able to leverage a
large percentage of the code and infrastructure already developed for Unladen
Swallows JIT compiler. Indeed, these two compilation strategies could exist
side by side.</p>
</section>
</section>
<section id="future-work">
<h2><a class="toc-backref" href="#future-work" role="doc-backlink">Future Work</a></h2>
<p>A JIT compiler is an extremely flexible tool, and we have by no means exhausted
its full potential. Unladen Swallow maintains a list of yet-to-be-implemented
performance optimizations <a class="footnote-reference brackets" href="#us-perf-punchlist" id="id116">[50]</a> that the team has not yet
had time to fully implement. Examples:</p>
<ul class="simple">
<li>Python/Python inlining <a class="footnote-reference brackets" href="#inlining" id="id117">[67]</a>. Our compiler currently performs no
inlining between pure-Python functions. Work on this is on-going
<a class="footnote-reference brackets" href="#us-inlining" id="id118">[69]</a>.</li>
<li>Unboxing <a class="footnote-reference brackets" href="#unboxing" id="id119">[68]</a>. Unboxing is critical for numerical performance. PyPy
in particular has demonstrated the value of unboxing to heavily numeric
workloads.</li>
<li>Recompilation, adaptation. Unladen Swallow currently only compiles a Python
function once, based on its usage pattern up to that point. If the usage
pattern changes, limitations in LLVM <a class="footnote-reference brackets" href="#us-recompile-issue" id="id120">[73]</a> prevent us from
recompiling the function to better serve the new usage pattern.</li>
<li>JIT-compile regular expressions. Modern JavaScript engines reuse their JIT
compilation infrastructure to boost regex performance <a class="footnote-reference brackets" href="#us-regex-perf" id="id121">[74]</a>.
Unladen Swallow has developed benchmarks for Python regular expression
performance (<a class="footnote-reference brackets" href="#us-bm-re-compile" id="id122">[75]</a>, <a class="footnote-reference brackets" href="#us-bm-re-v8" id="id123">[76]</a>, <a class="footnote-reference brackets" href="#us-bm-re-effbot" id="id124">[77]</a>), but
work on regex performance is still at an early stage <a class="footnote-reference brackets" href="#us-regex-issue" id="id125">[78]</a>.</li>
<li>Trace compilation <a class="footnote-reference brackets" href="#traces-waste-of-time" id="id126">[92]</a>, <a class="footnote-reference brackets" href="#traces-explicit-pipeline" id="id127">[93]</a>.
Based on the results of PyPy and Tracemonkey <a class="footnote-reference brackets" href="#tracemonkey" id="id128">[94]</a>, we believe that
a CPython JIT should incorporate trace compilation to some degree. We
initially avoided a purely-tracing JIT compiler in favor of a simpler,
function-at-a-time compiler. However this function-at-a-time compiler has laid
the groundwork for a future tracing compiler implemented in the same terms.</li>
<li>Profile generation/reuse. The runtime data gathered by the JIT could be
persisted to disk and reused by subsequent JIT compilations, or by external
tools such as Cython <a class="footnote-reference brackets" href="#cython" id="id129">[102]</a> or a feedback-enhanced code coverage tool.</li>
</ul>
<p>This list is by no means exhaustive. There is a vast literature on optimizations
for dynamic languages that could and should be implemented in terms of Unladen
Swallows LLVM-based JIT compiler <a class="footnote-reference brackets" href="#us-relevantpapers" id="id130">[54]</a>.</p>
</section>
<section id="unladen-swallow-community">
<h2><a class="toc-backref" href="#unladen-swallow-community" role="doc-backlink">Unladen Swallow Community</a></h2>
<p>We would like to thank the community of developers who have contributed to
Unladen Swallow, in particular: James Abbatiello, Joerg Blank, Eric Christopher,
Alex Gaynor, Chris Lattner, Nick Lewycky, Evan Phoenix and Thomas Wouters.</p>
</section>
<section id="licensing">
<h2><a class="toc-backref" href="#licensing" role="doc-backlink">Licensing</a></h2>
<p>All work on Unladen Swallow is licensed to the Python Software Foundation (PSF)
under the terms of the Python Software Foundation License v2 <a class="footnote-reference brackets" href="#psf-lic" id="id131">[56]</a> under
the umbrella of Googles blanket Contributor License Agreement with the PSF.</p>
<p>LLVM is licensed <a class="footnote-reference brackets" href="#llvm-lic" id="id132">[57]</a> under the University of llinois/NCSA Open Source
License <a class="footnote-reference brackets" href="#ui-lic" id="id133">[58]</a>, a liberal, OSI-approved license. The University of Illinois
Urbana-Champaign is the sole copyright holder for LLVM.</p>
</section>
<section id="references">
<h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="us-post-mortem" role="doc-footnote">
<dt class="label" id="us-post-mortem">[<a href="#id1">1</a>]</dt>
<dd><a class="reference external" href="http://qinsb.blogspot.com/2011/03/unladen-swallow-retrospective.html">http://qinsb.blogspot.com/2011/03/unladen-swallow-retrospective.html</a></aside>
<aside class="footnote brackets" id="dead-parrot" role="doc-footnote">
<dt class="label" id="dead-parrot">[<a href="#id2">2</a>]</dt>
<dd><a class="reference external" href="http://en.wikipedia.org/wiki/Dead_Parrot_sketch">http://en.wikipedia.org/wiki/Dead_Parrot_sketch</a></aside>
<aside class="footnote brackets" id="us" role="doc-footnote">
<dt class="label" id="us">[<a href="#id3">3</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/">http://code.google.com/p/unladen-swallow/</a></aside>
<aside class="footnote brackets" id="llvm" role="doc-footnote">
<dt class="label" id="llvm">[<a href="#id15">4</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/">http://llvm.org/</a></aside>
<aside class="footnote brackets" id="clang" role="doc-footnote">
<dt class="label" id="clang">[<a href="#id110">5</a>]</dt>
<dd><a class="reference external" href="http://clang.llvm.org/">http://clang.llvm.org/</a></aside>
<aside class="footnote brackets" id="tested-apps" role="doc-footnote">
<dt class="label" id="tested-apps">[<a href="#id58">6</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/wiki/Testing">http://code.google.com/p/unladen-swallow/wiki/Testing</a></aside>
<aside class="footnote brackets" id="llvm-hardware" role="doc-footnote">
<dt class="label" id="llvm-hardware">[<a href="#id79">7</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/docs/GettingStarted.html#hardware">http://llvm.org/docs/GettingStarted.html#hardware</a></aside>
<aside class="footnote brackets" id="llvm-c-api" role="doc-footnote">
<dt class="label" id="llvm-c-api">[<a href="#id95">8</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/</a></aside>
<aside class="footnote brackets" id="llvm-26-whatsnew" role="doc-footnote">
<dt class="label" id="llvm-26-whatsnew">[<a href="#id100">9</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/releases/2.6/docs/ReleaseNotes.html#whatsnew">http://llvm.org/releases/2.6/docs/ReleaseNotes.html#whatsnew</a></aside>
<aside class="footnote brackets" id="us-llvm-r820" role="doc-footnote">
<dt class="label" id="us-llvm-r820">[<a href="#id101">10</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/detail?r=820">http://code.google.com/p/unladen-swallow/source/detail?r=820</a></aside>
<aside class="footnote brackets" id="us-llvm-r532" role="doc-footnote">
<dt class="label" id="us-llvm-r532">[<a href="#id102">11</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/detail?r=532">http://code.google.com/p/unladen-swallow/source/detail?r=532</a></aside>
<aside class="footnote brackets" id="llvm-macports" role="doc-footnote">
<dt class="label" id="llvm-macports">[<a href="#id103">12</a>]</dt>
<dd><a class="reference external" href="http://trac.macports.org/browser/trunk/dports/lang/llvm/Portfile">http://trac.macports.org/browser/trunk/dports/lang/llvm/Portfile</a></aside>
<aside class="footnote brackets" id="llvm-ubuntu" role="doc-footnote">
<dt class="label" id="llvm-ubuntu">[<a href="#id104">13</a>]</dt>
<dd><a class="reference external" href="http://packages.ubuntu.com/karmic/llvm">http://packages.ubuntu.com/karmic/llvm</a></aside>
<aside class="footnote brackets" id="llvm-debian" role="doc-footnote">
<dt class="label" id="llvm-debian">[<a href="#id105">14</a>]</dt>
<dd><a class="reference external" href="http://packages.debian.org/unstable/devel/llvm">http://packages.debian.org/unstable/devel/llvm</a></aside>
<aside class="footnote brackets" id="clang-debian" role="doc-footnote">
<dt class="label" id="clang-debian">[<a href="#id111">15</a>]</dt>
<dd><a class="reference external" href="http://packages.debian.org/sid/clang">http://packages.debian.org/sid/clang</a></aside>
<aside class="footnote brackets" id="llvm-fedora" role="doc-footnote">
<dt class="label" id="llvm-fedora">[<a href="#id106">16</a>]</dt>
<dd><a class="reference external" href="http://koji.fedoraproject.org/koji/buildinfo?buildID=134384">http://koji.fedoraproject.org/koji/buildinfo?buildID=134384</a></aside>
<aside class="footnote brackets" id="gdb70" role="doc-footnote">
<dt class="label" id="gdb70">[<a href="#id87">17</a>]</dt>
<dd><a class="reference external" href="http://www.gnu.org/software/gdb/download/ANNOUNCEMENT">http://www.gnu.org/software/gdb/download/ANNOUNCEMENT</a></aside>
<aside class="footnote brackets" id="oprofile" role="doc-footnote">
<dt class="label" id="oprofile">[<a href="#id88">18</a>]</dt>
<dd><a class="reference external" href="http://oprofile.sourceforge.net/news/">http://oprofile.sourceforge.net/news/</a></aside>
<aside class="footnote brackets" id="us-oprofile-punchlist" role="doc-footnote">
<dt class="label" id="us-oprofile-punchlist">[<a href="#id89">19</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/detail?id=63">http://code.google.com/p/unladen-swallow/issues/detail?id=63</a></aside>
<aside class="footnote brackets" id="shark" role="doc-footnote">
<dt class="label" id="shark">[<a href="#id90">20</a>]</dt>
<dd><a class="reference external" href="http://developer.apple.com/tools/sharkoptimize.html">http://developer.apple.com/tools/sharkoptimize.html</a></aside>
<aside class="footnote brackets" id="llvm-oprofile-change" role="doc-footnote">
<dt class="label" id="llvm-oprofile-change">[<a href="#id91">21</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/viewvc/llvm-project?view=rev&amp;revision=75279">http://llvm.org/viewvc/llvm-project?view=rev&amp;revision=75279</a></aside>
<aside class="footnote brackets" id="us-oprofile-change" role="doc-footnote">
<dt class="label" id="us-oprofile-change">[<a href="#id92">22</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/detail?r=986">http://code.google.com/p/unladen-swallow/source/detail?r=986</a></aside>
<aside class="footnote brackets" id="oprofile-jit-interface" role="doc-footnote">
<dt class="label" id="oprofile-jit-interface">[<a href="#id93">23</a>]</dt>
<dd><a class="reference external" href="http://oprofile.sourceforge.net/doc/devel/jit-interface.html">http://oprofile.sourceforge.net/doc/devel/jit-interface.html</a></aside>
<aside class="footnote brackets" id="oprofile-workflow" role="doc-footnote">
<dt class="label" id="oprofile-workflow">[<a href="#id94">24</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/wiki/UsingOProfile">http://code.google.com/p/unladen-swallow/wiki/UsingOProfile</a></aside>
<aside class="footnote brackets" id="llvm-mingw" role="doc-footnote">
<dt class="label" id="llvm-mingw">[<a href="#id107">25</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/releases/download.html">http://llvm.org/releases/download.html</a></aside>
<aside class="footnote brackets" id="us-r359" role="doc-footnote">
<dt class="label" id="us-r359">[<a href="#id83">26</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/detail?r=359">http://code.google.com/p/unladen-swallow/source/detail?r=359</a></aside>
<aside class="footnote brackets" id="us-r376" role="doc-footnote">
<dt class="label" id="us-r376">[<a href="#id84">27</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/detail?r=376">http://code.google.com/p/unladen-swallow/source/detail?r=376</a></aside>
<aside class="footnote brackets" id="us-r417" role="doc-footnote">
<dt class="label" id="us-r417">[<a href="#id85">28</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/detail?r=417">http://code.google.com/p/unladen-swallow/source/detail?r=417</a></aside>
<aside class="footnote brackets" id="us-r517" role="doc-footnote">
<dt class="label" id="us-r517">[<a href="#id86">29</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/detail?r=517">http://code.google.com/p/unladen-swallow/source/detail?r=517</a></aside>
<aside class="footnote brackets" id="bdfl-27-final" role="doc-footnote">
<dt class="label" id="bdfl-27-final">[<a href="#id112">30</a>]</dt>
<dd><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2010-January/095682.html">https://mail.python.org/pipermail/python-dev/2010-January/095682.html</a></aside>
<aside class="footnote brackets" id="us-punchlist" role="doc-footnote">
<dt class="label" id="us-punchlist">[31]<em> (<a href='#id4'>1</a>, <a href='#id113'>2</a>) </em></dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/list?q=label:Merger">http://code.google.com/p/unladen-swallow/issues/list?q=label:Merger</a></aside>
<aside class="footnote brackets" id="us-binary-size" role="doc-footnote">
<dt class="label" id="us-binary-size">[<a href="#id44">32</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/detail?id=118">http://code.google.com/p/unladen-swallow/issues/detail?id=118</a></aside>
<aside class="footnote brackets" id="us-issue-startup-time" role="doc-footnote">
<dt class="label" id="us-issue-startup-time">[<a href="#id43">33</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/detail?id=64">http://code.google.com/p/unladen-swallow/issues/detail?id=64</a></aside>
<aside class="footnote brackets" id="zope-interface" role="doc-footnote">
<dt class="label" id="zope-interface">[<a href="#id59">34</a>]</dt>
<dd><a class="reference external" href="http://www.zope.org/Products/ZopeInterface">http://www.zope.org/Products/ZopeInterface</a></aside>
<aside class="footnote brackets" id="bigtable" role="doc-footnote">
<dt class="label" id="bigtable">[<a href="#id61">35</a>]</dt>
<dd><a class="reference external" href="http://en.wikipedia.org/wiki/BigTable">http://en.wikipedia.org/wiki/BigTable</a></aside>
<aside class="footnote brackets" id="mondrian" role="doc-footnote">
<dt class="label" id="mondrian">[<a href="#id62">36</a>]</dt>
<dd><a class="reference external" href="http://www.niallkennedy.com/blog/2006/11/google-mondrian.html">http://www.niallkennedy.com/blog/2006/11/google-mondrian.html</a></aside>
<aside class="footnote brackets" id="us-sqlalchemy-readme" role="doc-footnote">
<dt class="label" id="us-sqlalchemy-readme">[<a href="#id60">37</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/browse/tests/lib/sqlalchemy/README.unladen">http://code.google.com/p/unladen-swallow/source/browse/tests/lib/sqlalchemy/README.unladen</a></aside>
<aside class="footnote brackets" id="us-test-llvm" role="doc-footnote">
<dt class="label" id="us-test-llvm">[<a href="#id65">38</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/browse/trunk/Lib/test/test_llvm.py">http://code.google.com/p/unladen-swallow/source/browse/trunk/Lib/test/test_llvm.py</a></aside>
<aside class="footnote brackets" id="fuzz-testing" role="doc-footnote">
<dt class="label" id="fuzz-testing">[<a href="#id66">39</a>]</dt>
<dd><a class="reference external" href="http://en.wikipedia.org/wiki/Fuzz_testing">http://en.wikipedia.org/wiki/Fuzz_testing</a></aside>
<aside class="footnote brackets" id="pyfuzz" role="doc-footnote">
<dt class="label" id="pyfuzz">[<a href="#id67">40</a>]</dt>
<dd><a class="reference external" href="http://bitbucket.org/ebo/pyfuzz/overview/">http://bitbucket.org/ebo/pyfuzz/overview/</a></aside>
<aside class="footnote brackets" id="fusil" role="doc-footnote">
<dt class="label" id="fusil">[<a href="#id68">41</a>]</dt>
<dd><a class="reference external" href="http://lwn.net/Articles/322826/">http://lwn.net/Articles/322826/</a></aside>
<aside class="footnote brackets" id="us-memory-issue" role="doc-footnote">
<dt class="label" id="us-memory-issue">[<a href="#id42">42</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/detail?id=68">http://code.google.com/p/unladen-swallow/issues/detail?id=68</a></aside>
<aside class="footnote brackets" id="us-benchmarks" role="doc-footnote">
<dt class="label" id="us-benchmarks">[43]<em> (<a href='#id31'>1</a>, <a href='#id37'>2</a>) </em></dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/wiki/Benchmarks">http://code.google.com/p/unladen-swallow/wiki/Benchmarks</a></aside>
<aside class="footnote brackets" id="students-t-test" role="doc-footnote">
<dt class="label" id="students-t-test">[<a href="#id36">44</a>]</dt>
<dd><a class="reference external" href="http://en.wikipedia.org/wiki/Student's_t-test">http://en.wikipedia.org/wiki/Students_t-test</a></aside>
<aside class="footnote brackets" id="smaps" role="doc-footnote">
<dt class="label" id="smaps">[<a href="#id41">45</a>]</dt>
<dd><a class="reference external" href="http://bmaurer.blogspot.com/2006/03/memory-usage-with-smaps.html">http://bmaurer.blogspot.com/2006/03/memory-usage-with-smaps.html</a></aside>
<aside class="footnote brackets" id="us-background-thread" role="doc-footnote">
<dt class="label" id="us-background-thread">[<a href="#id38">46</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/browse/branches/background-thread">http://code.google.com/p/unladen-swallow/source/browse/branches/background-thread</a></aside>
<aside class="footnote brackets" id="us-background-thread-issue" role="doc-footnote">
<dt class="label" id="us-background-thread-issue">[47]<em> (<a href='#id39'>1</a>, <a href='#id71'>2</a>) </em></dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/detail?id=40">http://code.google.com/p/unladen-swallow/issues/detail?id=40</a></aside>
<aside class="footnote brackets" id="us-import-tests" role="doc-footnote">
<dt class="label" id="us-import-tests">[<a href="#id63">48</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/detail?r=888">http://code.google.com/p/unladen-swallow/source/detail?r=888</a></aside>
<aside class="footnote brackets" id="us-tracing-tests" role="doc-footnote">
<dt class="label" id="us-tracing-tests">[<a href="#id64">49</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/diff?spec=svn576&amp;r=576&amp;format=side&amp;path=/trunk/Lib/test/test_trace.py">http://code.google.com/p/unladen-swallow/source/diff?spec=svn576&amp;r=576&amp;format=side&amp;path=/trunk/Lib/test/test_trace.py</a></aside>
<aside class="footnote brackets" id="us-perf-punchlist" role="doc-footnote">
<dt class="label" id="us-perf-punchlist">[50]<em> (<a href='#id40'>1</a>, <a href='#id116'>2</a>) </em></dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/list?q=label:Performance">http://code.google.com/p/unladen-swallow/issues/list?q=label:Performance</a></aside>
<aside class="footnote brackets" id="jit" role="doc-footnote">
<dt class="label" id="jit">[<a href="#id5">51</a>]</dt>
<dd><a class="reference external" href="http://en.wikipedia.org/wiki/Just-in-time_compilation">http://en.wikipedia.org/wiki/Just-in-time_compilation</a></aside>
<aside class="footnote brackets" id="urs-self" role="doc-footnote">
<dt class="label" id="urs-self">[52]<em> (<a href='#id6'>1</a>, <a href='#id54'>2</a>) </em></dt>
<dd><a class="reference external" href="http://research.sun.com/self/papers/urs-thesis.html">http://research.sun.com/self/papers/urs-thesis.html</a></aside>
<aside class="footnote brackets" id="us-projectplan" role="doc-footnote">
<dt class="label" id="us-projectplan">[<a href="#id17">53</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/wiki/ProjectPlan">http://code.google.com/p/unladen-swallow/wiki/ProjectPlan</a></aside>
<aside class="footnote brackets" id="us-relevantpapers" role="doc-footnote">
<dt class="label" id="us-relevantpapers">[54]<em> (<a href='#id13'>1</a>, <a href='#id130'>2</a>) </em></dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/wiki/RelevantPapers">http://code.google.com/p/unladen-swallow/wiki/RelevantPapers</a></aside>
<aside class="footnote brackets" id="us-llvm-notes" role="doc-footnote">
<dt class="label" id="us-llvm-notes">[55]<em> (<a href='#id14'>1</a>, <a href='#id18'>2</a>) </em></dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/browse/trunk/Python/llvm_notes.txt">http://code.google.com/p/unladen-swallow/source/browse/trunk/Python/llvm_notes.txt</a></aside>
<aside class="footnote brackets" id="psf-lic" role="doc-footnote">
<dt class="label" id="psf-lic">[<a href="#id131">56</a>]</dt>
<dd><a class="reference external" href="http://www.python.org/psf/license/">http://www.python.org/psf/license/</a></aside>
<aside class="footnote brackets" id="llvm-lic" role="doc-footnote">
<dt class="label" id="llvm-lic">[<a href="#id132">57</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/docs/DeveloperPolicy.html#clp">http://llvm.org/docs/DeveloperPolicy.html#clp</a></aside>
<aside class="footnote brackets" id="ui-lic" role="doc-footnote">
<dt class="label" id="ui-lic">[<a href="#id133">58</a>]</dt>
<dd><a class="reference external" href="http://www.opensource.org/licenses/UoI-NCSA.php">http://www.opensource.org/licenses/UoI-NCSA.php</a></aside>
<aside class="footnote brackets" id="v8" role="doc-footnote">
<dt class="label" id="v8">[<a href="#id7">59</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/v8/">http://code.google.com/p/v8/</a></aside>
<aside class="footnote brackets" id="squirrelfishextreme" role="doc-footnote">
<dt class="label" id="squirrelfishextreme">[<a href="#id8">60</a>]</dt>
<dd><a class="reference external" href="http://webkit.org/blog/214/introducing-squirrelfish-extreme/">http://webkit.org/blog/214/introducing-squirrelfish-extreme/</a></aside>
<aside class="footnote brackets" id="rubinius" role="doc-footnote">
<dt class="label" id="rubinius">[61]<em> (<a href='#id10'>1</a>, <a href='#id46'>2</a>) </em></dt>
<dd><a class="reference external" href="http://rubini.us/">http://rubini.us/</a></aside>
<aside class="footnote brackets" id="parrot-on-llvm" role="doc-footnote">
<dt class="label" id="parrot-on-llvm">[62]</dt>
<dd><a class="reference external" href="http://lists.parrot.org/pipermail/parrot-dev/2009-September/002811.html">http://lists.parrot.org/pipermail/parrot-dev/2009-September/002811.html</a></aside>
<aside class="footnote brackets" id="macruby" role="doc-footnote">
<dt class="label" id="macruby">[63]<em> (<a href='#id11'>1</a>, <a href='#id47'>2</a>) </em></dt>
<dd><a class="reference external" href="http://www.macruby.org/">http://www.macruby.org/</a></aside>
<aside class="footnote brackets" id="hotspot" role="doc-footnote">
<dt class="label" id="hotspot">[<a href="#id9">64</a>]</dt>
<dd><a class="reference external" href="http://en.wikipedia.org/wiki/HotSpot">http://en.wikipedia.org/wiki/HotSpot</a></aside>
<aside class="footnote brackets" id="psyco" role="doc-footnote">
<dt class="label" id="psyco">[65]<em> (<a href='#id12'>1</a>, <a href='#id26'>2</a>, <a href='#id69'>3</a>) </em></dt>
<dd><a class="reference external" href="http://psyco.sourceforge.net/">http://psyco.sourceforge.net/</a></aside>
<aside class="footnote brackets" id="pypy" role="doc-footnote">
<dt class="label" id="pypy">[<a href="#id27">66</a>]</dt>
<dd><a class="reference external" href="http://codespeak.net/pypy/dist/pypy/doc/">http://codespeak.net/pypy/dist/pypy/doc/</a></aside>
<aside class="footnote brackets" id="inlining" role="doc-footnote">
<dt class="label" id="inlining">[<a href="#id117">67</a>]</dt>
<dd><a class="reference external" href="http://en.wikipedia.org/wiki/Inline_expansion">http://en.wikipedia.org/wiki/Inline_expansion</a></aside>
<aside class="footnote brackets" id="unboxing" role="doc-footnote">
<dt class="label" id="unboxing">[<a href="#id119">68</a>]</dt>
<dd><a class="reference external" href="http://en.wikipedia.org/wiki/Object_type_(object-oriented_programming%29">http://en.wikipedia.org/wiki/Object_type_(object-oriented_programming%29</a></aside>
<aside class="footnote brackets" id="us-inlining" role="doc-footnote">
<dt class="label" id="us-inlining">[<a href="#id118">69</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/detail?id=86">http://code.google.com/p/unladen-swallow/issues/detail?id=86</a></aside>
<aside class="footnote brackets" id="us-styleguide" role="doc-footnote">
<dt class="label" id="us-styleguide">[<a href="#id97">70</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/wiki/StyleGuide">http://code.google.com/p/unladen-swallow/wiki/StyleGuide</a></aside>
<aside class="footnote brackets" id="llvm-styleguide" role="doc-footnote">
<dt class="label" id="llvm-styleguide">[<a href="#id98">71</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/docs/CodingStandards.html">http://llvm.org/docs/CodingStandards.html</a></aside>
<aside class="footnote brackets" id="google-styleguide" role="doc-footnote">
<dt class="label" id="google-styleguide">[<a href="#id99">72</a>]</dt>
<dd><a class="reference external" href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml">http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml</a></aside>
<aside class="footnote brackets" id="us-recompile-issue" role="doc-footnote">
<dt class="label" id="us-recompile-issue">[<a href="#id120">73</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/detail?id=41">http://code.google.com/p/unladen-swallow/issues/detail?id=41</a></aside>
<aside class="footnote brackets" id="us-regex-perf" role="doc-footnote">
<dt class="label" id="us-regex-perf">[<a href="#id121">74</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/wiki/ProjectPlan#Regular_Expressions">http://code.google.com/p/unladen-swallow/wiki/ProjectPlan#Regular_Expressions</a></aside>
<aside class="footnote brackets" id="us-bm-re-compile" role="doc-footnote">
<dt class="label" id="us-bm-re-compile">[<a href="#id122">75</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/browse/tests/performance/bm_regex_compile.py">http://code.google.com/p/unladen-swallow/source/browse/tests/performance/bm_regex_compile.py</a></aside>
<aside class="footnote brackets" id="us-bm-re-v8" role="doc-footnote">
<dt class="label" id="us-bm-re-v8">[<a href="#id123">76</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/browse/tests/performance/bm_regex_v8.py">http://code.google.com/p/unladen-swallow/source/browse/tests/performance/bm_regex_v8.py</a></aside>
<aside class="footnote brackets" id="us-bm-re-effbot" role="doc-footnote">
<dt class="label" id="us-bm-re-effbot">[<a href="#id124">77</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/browse/tests/performance/bm_regex_effbot.py">http://code.google.com/p/unladen-swallow/source/browse/tests/performance/bm_regex_effbot.py</a></aside>
<aside class="footnote brackets" id="us-regex-issue" role="doc-footnote">
<dt class="label" id="us-regex-issue">[<a href="#id125">78</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/detail?id=13">http://code.google.com/p/unladen-swallow/issues/detail?id=13</a></aside>
<aside class="footnote brackets" id="pygame" role="doc-footnote">
<dt class="label" id="pygame">[<a href="#id70">79</a>]</dt>
<dd><a class="reference external" href="http://www.pygame.org/">http://www.pygame.org/</a></aside>
<aside class="footnote brackets" id="numpy" role="doc-footnote">
<dt class="label" id="numpy">[<a href="#id34">80</a>]</dt>
<dd><a class="reference external" href="http://numpy.scipy.org/">http://numpy.scipy.org/</a></aside>
<aside class="footnote brackets" id="pypy-bmarks" role="doc-footnote">
<dt class="label" id="pypy-bmarks">[<a href="#id32">81</a>]</dt>
<dd><a class="reference external" href="http://codespeak.net:8099/plotsummary.html">http://codespeak.net:8099/plotsummary.html</a></aside>
<aside class="footnote brackets" id="llvm-users" role="doc-footnote">
<dt class="label" id="llvm-users">[<a href="#id45">82</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/Users.html">http://llvm.org/Users.html</a></aside>
<aside class="footnote brackets" id="hlvm" role="doc-footnote">
<dt class="label" id="hlvm">[<a href="#id48">83</a>]</dt>
<dd><a class="reference external" href="http://www.ffconsultancy.com/ocaml/hlvm/">http://www.ffconsultancy.com/ocaml/hlvm/</a></aside>
<aside class="footnote brackets" id="llvm-far-call-issue" role="doc-footnote">
<dt class="label" id="llvm-far-call-issue">[84]<em> (<a href='#id49'>1</a>, <a href='#id81'>2</a>) </em></dt>
<dd><a class="reference external" href="http://llvm.org/PR5201">http://llvm.org/PR5201</a></aside>
<aside class="footnote brackets" id="llvm-jmm-rev" role="doc-footnote">
<dt class="label" id="llvm-jmm-rev">[<a href="#id50">85</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/viewvc/llvm-project?view=rev&amp;revision=76828">http://llvm.org/viewvc/llvm-project?view=rev&amp;revision=76828</a></aside>
<aside class="footnote brackets" id="llvm-memleak-rev" role="doc-footnote">
<dt class="label" id="llvm-memleak-rev">[<a href="#id52">86</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/viewvc/llvm-project?rev=91611&amp;view=rev">http://llvm.org/viewvc/llvm-project?rev=91611&amp;view=rev</a></aside>
<aside class="footnote brackets" id="llvm-globaldce-rev" role="doc-footnote">
<dt class="label" id="llvm-globaldce-rev">[<a href="#id51">87</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/viewvc/llvm-project?rev=85182&amp;view=rev">http://llvm.org/viewvc/llvm-project?rev=85182&amp;view=rev</a></aside>
<aside class="footnote brackets" id="llvm-availext-issue" role="doc-footnote">
<dt class="label" id="llvm-availext-issue">[<a href="#id53">88</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/PR5735">http://llvm.org/PR5735</a></aside>
<aside class="footnote brackets" id="us-specialization-issue" role="doc-footnote">
<dt class="label" id="us-specialization-issue">[<a href="#id55">89</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/detail?id=73">http://code.google.com/p/unladen-swallow/issues/detail?id=73</a></aside>
<aside class="footnote brackets" id="us-direct-calling-issue" role="doc-footnote">
<dt class="label" id="us-direct-calling-issue">[<a href="#id56">90</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/detail?id=88">http://code.google.com/p/unladen-swallow/issues/detail?id=88</a></aside>
<aside class="footnote brackets" id="us-fast-globals-issue" role="doc-footnote">
<dt class="label" id="us-fast-globals-issue">[<a href="#id57">91</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/detail?id=67">http://code.google.com/p/unladen-swallow/issues/detail?id=67</a></aside>
<aside class="footnote brackets" id="traces-waste-of-time" role="doc-footnote">
<dt class="label" id="traces-waste-of-time">[<a href="#id126">92</a>]</dt>
<dd><a class="reference external" href="http://www.ics.uci.edu/~franz/Site/pubs-pdf/C44Prepub.pdf">http://www.ics.uci.edu/~franz/Site/pubs-pdf/C44Prepub.pdf</a></aside>
<aside class="footnote brackets" id="traces-explicit-pipeline" role="doc-footnote">
<dt class="label" id="traces-explicit-pipeline">[<a href="#id127">93</a>]</dt>
<dd><a class="reference external" href="http://www.ics.uci.edu/~franz/Site/pubs-pdf/ICS-TR-07-12.pdf">http://www.ics.uci.edu/~franz/Site/pubs-pdf/ICS-TR-07-12.pdf</a></aside>
<aside class="footnote brackets" id="tracemonkey" role="doc-footnote">
<dt class="label" id="tracemonkey">[<a href="#id128">94</a>]</dt>
<dd><a class="reference external" href="https://wiki.mozilla.org/JavaScript:TraceMonkey">https://wiki.mozilla.org/JavaScript:TraceMonkey</a></aside>
<aside class="footnote brackets" id="llvm-langref" role="doc-footnote">
<dt class="label" id="llvm-langref">[<a href="#id16">95</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/docs/LangRef.html">http://llvm.org/docs/LangRef.html</a></aside>
<aside class="footnote brackets" id="us-wider-perf-issue" role="doc-footnote">
<dt class="label" id="us-wider-perf-issue">[<a href="#id33">96</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/detail?id=120">http://code.google.com/p/unladen-swallow/issues/detail?id=120</a></aside>
<aside class="footnote brackets" id="us-nbody" role="doc-footnote">
<dt class="label" id="us-nbody">[<a href="#id35">97</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/source/browse/tests/performance/bm_nbody.py">http://code.google.com/p/unladen-swallow/source/browse/tests/performance/bm_nbody.py</a></aside>
<aside class="footnote brackets" id="us-shared-link-issue" role="doc-footnote">
<dt class="label" id="us-shared-link-issue">[<a href="#id108">98</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/detail?id=130">http://code.google.com/p/unladen-swallow/issues/detail?id=130</a></aside>
<aside class="footnote brackets" id="us-llvm-punchlist" role="doc-footnote">
<dt class="label" id="us-llvm-punchlist">[<a href="#id109">99</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/unladen-swallow/issues/detail?id=131">http://code.google.com/p/unladen-swallow/issues/detail?id=131</a></aside>
<aside class="footnote brackets" id="llvm-ppc-eager-jit-issue" role="doc-footnote">
<dt class="label" id="llvm-ppc-eager-jit-issue">[<a href="#id80">100</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/PR4816">http://llvm.org/PR4816</a></aside>
<aside class="footnote brackets" id="llvm-arm-jit-issue" role="doc-footnote">
<dt class="label" id="llvm-arm-jit-issue">[<a href="#id82">101</a>]</dt>
<dd><a class="reference external" href="http://llvm.org/PR6065">http://llvm.org/PR6065</a></aside>
<aside class="footnote brackets" id="cython" role="doc-footnote">
<dt class="label" id="cython">[102]<em> (<a href='#id19'>1</a>, <a href='#id129'>2</a>) </em></dt>
<dd><a class="reference external" href="http://www.cython.org/">http://www.cython.org/</a></aside>
<aside class="footnote brackets" id="shedskin" role="doc-footnote">
<dt class="label" id="shedskin">[<a href="#id20">103</a>]</dt>
<dd><a class="reference external" href="http://shed-skin.blogspot.com/">http://shed-skin.blogspot.com/</a></aside>
<aside class="footnote brackets" id="shedskin-library-limits" role="doc-footnote">
<dt class="label" id="shedskin-library-limits">[<a href="#id21">104</a>]</dt>
<dd><a class="reference external" href="http://shedskin.googlecode.com/files/shedskin-tutorial-0.3.html">http://shedskin.googlecode.com/files/shedskin-tutorial-0.3.html</a></aside>
<aside class="footnote brackets" id="wpython" role="doc-footnote">
<dt class="label" id="wpython">[105]<em> (<a href='#id29'>1</a>, <a href='#id72'>2</a>) </em></dt>
<dd><a class="reference external" href="http://code.google.com/p/wpython/">http://code.google.com/p/wpython/</a></aside>
<aside class="footnote brackets" id="wpython-performance" role="doc-footnote">
<dt class="label" id="wpython-performance">[<a href="#id30">106</a>]</dt>
<dd><a class="reference external" href="http://www.mail-archive.com/python-dev&#64;python.org/msg45143.html">http://www.mail-archive.com/python-dev&#64;python.org/msg45143.html</a></aside>
<aside class="footnote brackets" id="ironpython" role="doc-footnote">
<dt class="label" id="ironpython">[<a href="#id22">107</a>]</dt>
<dd><a class="reference external" href="http://ironpython.net/">http://ironpython.net/</a></aside>
<aside class="footnote brackets" id="mono" role="doc-footnote">
<dt class="label" id="mono">[<a href="#id23">108</a>]</dt>
<dd><a class="reference external" href="http://www.mono-project.com/">http://www.mono-project.com/</a></aside>
<aside class="footnote brackets" id="jython" role="doc-footnote">
<dt class="label" id="jython">[<a href="#id24">109</a>]</dt>
<dd><a class="reference external" href="http://www.jython.org/">http://www.jython.org/</a></aside>
<aside class="footnote brackets" id="jython-c-ext" role="doc-footnote">
<dt class="label" id="jython-c-ext">[<a href="#id25">110</a>]</dt>
<dd><a class="reference external" href="http://wiki.python.org/jython/JythonFaq/GeneralInfo">http://wiki.python.org/jython/JythonFaq/GeneralInfo</a></aside>
<aside class="footnote brackets" id="pyv8" role="doc-footnote">
<dt class="label" id="pyv8">[<a href="#id28">111</a>]</dt>
<dd><a class="reference external" href="http://code.google.com/p/pyv8/">http://code.google.com/p/pyv8/</a></aside>
<aside class="footnote brackets" id="gcc-fdo" role="doc-footnote">
<dt class="label" id="gcc-fdo">[<a href="#id114">112</a>]</dt>
<dd><a class="reference external" href="http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html">http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html</a></aside>
<aside class="footnote brackets" id="msvc-pgo" role="doc-footnote">
<dt class="label" id="msvc-pgo">[<a href="#id115">113</a>]</dt>
<dd><a class="reference external" href="http://msdn.microsoft.com/en-us/library/e7k32f4k.aspx">http://msdn.microsoft.com/en-us/library/e7k32f4k.aspx</a></aside>
<aside class="footnote brackets" id="us-wpython-compat" role="doc-footnote">
<dt class="label" id="us-wpython-compat">[<a href="#id73">114</a>]</dt>
<dd><a class="reference external" href="http://www.mail-archive.com/python-dev&#64;python.org/msg44962.html">http://www.mail-archive.com/python-dev&#64;python.org/msg44962.html</a></aside>
<aside class="footnote brackets" id="asher-rotem" role="doc-footnote">
<dt class="label" id="asher-rotem">[<a href="#id74">115</a>]</dt>
<dd><a class="reference external" href="http://portal.acm.org/citation.cfm?id=1534530.1534550">http://portal.acm.org/citation.cfm?id=1534530.1534550</a></aside>
<aside class="footnote brackets" id="stackless" role="doc-footnote">
<dt class="label" id="stackless">[<a href="#id75">116</a>]</dt>
<dd><a class="reference external" href="http://www.stackless.com/">http://www.stackless.com/</a></aside>
<aside class="footnote brackets" id="stackless-merger" role="doc-footnote">
<dt class="label" id="stackless-merger">[<a href="#id76">117</a>]</dt>
<dd><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2004-June/045165.html">https://mail.python.org/pipermail/python-dev/2004-June/045165.html</a></aside>
<aside class="footnote brackets" id="llvm-heap-frames" role="doc-footnote">
<dt class="label" id="llvm-heap-frames">[<a href="#id77">118</a>]</dt>
<dd><a class="reference external" href="http://www.nondot.org/sabre/LLVMNotes/ExplicitlyManagedStackFrames.txt">http://www.nondot.org/sabre/LLVMNotes/ExplicitlyManagedStackFrames.txt</a></aside>
<aside class="footnote brackets" id="llvm-heap-frames-disc" role="doc-footnote">
<dt class="label" id="llvm-heap-frames-disc">[<a href="#id78">119</a>]</dt>
<dd><a class="reference external" href="http://old.nabble.com/LLVM-and-coroutines-microthreads-td23080883.html">http://old.nabble.com/LLVM-and-coroutines-microthreads-td23080883.html</a></aside>
<aside class="footnote brackets" id="pep7-cpp" role="doc-footnote">
<dt class="label" id="pep7-cpp">[<a href="#id96">120</a>]</dt>
<dd><a class="reference external" href="http://www.mail-archive.com/python-dev&#64;python.org/msg45544.html">http://www.mail-archive.com/python-dev&#64;python.org/msg45544.html</a></aside>
</aside>
</section>
<section id="copyright">
<h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2>
<p>This document has been placed in the public domain.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-3146.rst">https://github.com/python/peps/blob/main/peps/pep-3146.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-3146.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#pep-withdrawal">PEP Withdrawal</a></li>
<li><a class="reference internal" href="#abstract">Abstract</a></li>
<li><a class="reference internal" href="#rationale-implementation">Rationale, Implementation</a><ul>
<li><a class="reference internal" href="#alternatives">Alternatives</a></li>
</ul>
</li>
<li><a class="reference internal" href="#performance">Performance</a><ul>
<li><a class="reference internal" href="#benchmarks">Benchmarks</a></li>
<li><a class="reference internal" href="#performance-vs-cpython-2-6-4">Performance vs CPython 2.6.4</a></li>
<li><a class="reference internal" href="#memory-usage">Memory Usage</a></li>
<li><a class="reference internal" href="#start-up-time">Start-up Time</a></li>
<li><a class="reference internal" href="#binary-size">Binary Size</a></li>
<li><a class="reference internal" href="#performance-retrospective">Performance Retrospective</a></li>
</ul>
</li>
<li><a class="reference internal" href="#correctness-and-compatibility">Correctness and Compatibility</a><ul>
<li><a class="reference internal" href="#known-incompatibilities">Known Incompatibilities</a></li>
</ul>
</li>
<li><a class="reference internal" href="#platform-support">Platform Support</a></li>
<li><a class="reference internal" href="#impact-on-cpython-development">Impact on CPython Development</a><ul>
<li><a class="reference internal" href="#experimenting-with-changes-to-python-or-cpython-bytecode">Experimenting with Changes to Python or CPython Bytecode</a></li>
<li><a class="reference internal" href="#debugging">Debugging</a></li>
<li><a class="reference internal" href="#profiling">Profiling</a></li>
<li><a class="reference internal" href="#addition-of-c-to-cpython">Addition of C++ to CPython</a></li>
<li><a class="reference internal" href="#managing-llvm-releases-c-api-changes">Managing LLVM Releases, C++ API Changes</a></li>
<li><a class="reference internal" href="#building-cpython">Building CPython</a></li>
</ul>
</li>
<li><a class="reference internal" href="#proposed-merge-plan">Proposed Merge Plan</a><ul>
<li><a class="reference internal" href="#contingency-plans">Contingency Plans</a></li>
</ul>
</li>
<li><a class="reference internal" href="#future-work">Future Work</a></li>
<li><a class="reference internal" href="#unladen-swallow-community">Unladen Swallow Community</a></li>
<li><a class="reference internal" href="#licensing">Licensing</a></li>
<li><a class="reference internal" href="#references">References</a></li>
<li><a class="reference internal" href="#copyright">Copyright</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-3146.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>