1788 lines
126 KiB
HTML
1788 lines
126 KiB
HTML
|
|
|||
|
<!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 CPython’s 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 CPython’s 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> » </li>
|
|||
|
<li><a href="../pep-0000/">PEP Index</a> » </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 <collinwinter at google.com>,
|
|||
|
Jeffrey Yasskin <jyasskin at google.com>,
|
|||
|
Reid Kleckner <rnk at mit.edu></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
|
|||
|
CPython’s 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 Swallow’s 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 CPython’s 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 CPython’s 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 Swallow’s 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 CPython’s 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 Google’s 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 Hoelzle’s 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
|
|||
|
function’s 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 Swallow’s JIT works by compiling CPython
|
|||
|
bytecode to LLVM’s 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
|
|||
|
LLVM’s 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 CPython’s 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 CPython’s 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 Microsoft’s .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: PyPy’s 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
|
|||
|
CPython’s 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), Google’s 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 Google’s 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 NumPy’s 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, there’s 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 Student’s
|
|||
|
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 @ 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 @ 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 CPython’s 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 Swallow’s 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
|
|||
|
kernel’s <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 LLVM’s 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 Swallow’s <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 -> 0.352075: 1.6063x slower
|
|||
|
Avg: 0.227228 -> 0.364384: 1.6036x slower
|
|||
|
Significant (t=-51.879098, a=0.95)
|
|||
|
Stddev: 0.00762 -> 0.02532: 3.3227x larger
|
|||
|
Timeline: http://tinyurl.com/yfe8z3r
|
|||
|
|
|||
|
### startup_nosite ###
|
|||
|
Min: 0.105949 -> 0.264912: 2.5004x slower
|
|||
|
Avg: 0.107574 -> 0.267505: 2.4867x slower
|
|||
|
Significant (t=-703.557403, a=0.95)
|
|||
|
Stddev: 0.00214 -> 0.00240: 1.1209x larger
|
|||
|
Timeline: http://tinyurl.com/yajn8fa
|
|||
|
|
|||
|
### bzr_startup ###
|
|||
|
Min: 0.067990 -> 0.097985: 1.4412x slower
|
|||
|
Avg: 0.084322 -> 0.111348: 1.3205x slower
|
|||
|
Significant (t=-37.432534, a=0.95)
|
|||
|
Stddev: 0.00793 -> 0.00643: 1.2330x smaller
|
|||
|
Timeline: http://tinyurl.com/ybdm537
|
|||
|
|
|||
|
### hg_startup ###
|
|||
|
Min: 0.016997 -> 0.024997: 1.4707x slower
|
|||
|
Avg: 0.026990 -> 0.036772: 1.3625x slower
|
|||
|
Significant (t=-53.104502, a=0.95)
|
|||
|
Stddev: 0.00406 -> 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 Swallow’s
|
|||
|
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 LLVM’s 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 LLVM’s 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 Swallow’s 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 LLVM’s 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 LLVM’s 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>). LLVM’s 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 CPython’s 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 PyPy’s 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 Swallow’s 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 Swallow’s correctness test suite includes CPython’s 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 Google’s
|
|||
|
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 Google’s 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 CPython’s
|
|||
|
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 LLVM’s JIT compilation system <a class="footnote-reference brackets" href="#llvm-hardware" id="id79">[7]</a>. LLVM’s 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
|
|||
|
Swallow’s 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 LLVM’s 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 Swallow’s 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 you’re 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 Apple’s gdb or Microsoft’s 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
|
|||
|
Apple’s Shark <a class="footnote-reference brackets" href="#shark" id="id90">[20]</a> or Microsoft’s 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 CPython’s <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 LLVM’s 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 CPython’s 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 LLVM’s 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 LLVM’s 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 CPython’s 3.x line of
|
|||
|
development. The BDFL has indicated that 2.7 is to be the final release of
|
|||
|
CPython’s 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 gcc’s
|
|||
|
feedback-directed optimizations (<cite>-fprofile-generate</cite>) <a class="footnote-reference brackets" href="#gcc-fdo" id="id114">[112]</a> and
|
|||
|
Microsoft Visual Studio’s 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
|
|||
|
Swallow’s 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
|
|||
|
Swallow’s 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 Google’s 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&revision=75279">http://llvm.org/viewvc/llvm-project?view=rev&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/Student’s_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&r=576&format=side&path=/trunk/Lib/test/test_trace.py">http://code.google.com/p/unladen-swallow/source/diff?spec=svn576&r=576&format=side&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&revision=76828">http://llvm.org/viewvc/llvm-project?view=rev&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&view=rev">http://llvm.org/viewvc/llvm-project?rev=91611&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&view=rev">http://llvm.org/viewvc/llvm-project?rev=85182&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@python.org/msg45143.html">http://www.mail-archive.com/python-dev@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@python.org/msg44962.html">http://www.mail-archive.com/python-dev@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@python.org/msg45544.html">http://www.mail-archive.com/python-dev@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>
|