1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-04 19:10:37 -08:00
emacs/mps/manual/html/topic/critical.html
Gareth Rees bd034b6eb0 Update html.
Copied from Perforce
 Change: 180468
 ServerID: perforce.ravenbrook.com
2012-11-14 14:13:19 +00:00

396 lines
No EOL
31 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>3. The critical path &mdash; Memory Pool System 1.111.0 documentation</title>
<link rel="stylesheet" href="../_static/mps.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '1.111.0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="top" title="Memory Pool System 1.111.0 documentation" href="../index.html" />
<link rel="up" title="Internals" href="internals.html" />
<link rel="next" title="Introduction to memory management" href="../mmref/index.html" />
<link rel="prev" title="2. Platforms" href="platform.html" />
</head>
<body>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../mmref/index.html" title="Introduction to memory management"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="platform.html" title="2. Platforms"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">Memory Pool System 1.111.0 documentation</a> &raquo;</li>
<li><a href="internals.html" accesskey="U">Internals</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="the-critical-path">
<span id="topic-critical"></span><span id="index-0"></span><h1>3. The critical path<a class="headerlink" href="#the-critical-path" title="Permalink to this headline"></a></h1>
<p>The critical path is a key concept in the design of the Memory Pool
System. Code on the critical path is usually executed more than any
other code in the process. A change of just one instruction on the
critical path can make as much as a 1% difference in overall run-time.
The MPS is designed to make the critical path as short and fast as
possible.</p>
<div class="section" id="what-makes-the-critical-path-critical">
<h2>3.1. What makes the critical path critical<a class="headerlink" href="#what-makes-the-critical-path-critical" title="Permalink to this headline"></a></h2>
<p>In order to determine which objects can be recycled, the <a class="reference internal" href="../glossary/g.html#term-garbage-collector"><em class="xref std std-term">garbage
collector</em></a> has to frequently examine a very large number of pointers
in the program&#8217;s objects. It does this by <a class="reference internal" href="../glossary/s.html#term-scan"><em class="xref std std-term">scanning</em></a>
memory, both allocated objects and <a class="reference internal" href="../glossary/r.html#term-root"><em class="xref std std-term">roots</em></a> (such as the
<a class="reference internal" href="../glossary/t.html#term-thread"><em class="xref std std-term">threads&#8217;</em></a> <a class="reference internal" href="../glossary/c.html#term-control-stack"><em class="xref std std-term">control stacks</em></a>).</p>
<p>This means that the scanning functions must loop over pretty much
<em>every word in memory</em> sooner or later. The MPS takes great pains to
avoid scanning memory which does not need scanning, but to get good
performance, scanning must be highly optimised.</p>
<p>What&#8217;s more, the scanning functions apply an operation called &#8220;fix&#8221; to
every <a class="reference internal" href="../glossary/r.html#term-reference"><em class="xref std std-term">reference</em></a> (or potential reference) that they find in the
objects in memory. Fixing also attempts to eliminate uninteresting
pointers as fast as possible, but it has to do some work on every
object that is being considered for recycling, and that can be a large
proportion of the objects in existence. The path through fixing must
also be highly optimised, especially in the early stages.</p>
</div>
<div class="section" id="how-the-mps-avoids-scanning-and-fixing">
<h2>3.2. How the MPS avoids scanning and fixing<a class="headerlink" href="#how-the-mps-avoids-scanning-and-fixing" title="Permalink to this headline"></a></h2>
<p>Firstly, the MPS must occasionally decide which objects to try to
recycle. It does this using various facts it knows about the objects,
primarily their age and whether they&#8217;ve survived previous attempts at
recycling them. It then <a class="reference internal" href="../glossary/c.html#term-condemned-set"><em class="xref std std-term">condemns</em></a> a large
number of objects at once, and each of these objects must be
&#8220;preserved&#8221; by fixing references to them.</p>
<p>When the MPS condemns objects it chooses sets of objects in a small
set of &#8220;zones&#8221; in memory (preferably a single zone). The zone of an
object can be determined quickly from its address, without looking at
the object or any other data structure.</p>
<p>The MPS arranges that objects which it predicts will die at about the
same time are in the same zones.</p>
<p>The MPS allocates in &#8220;segments&#8221;. Each segment is of the order of one
&#8220;tract&#8221; of memory (generally the same as the operating system
<a class="reference internal" href="../glossary/p.html#term-page"><em class="xref std std-term">page</em></a> size, usually 4&nbsp;KiB or 8&nbsp;KiB) but may be larger if there
are large objects inside. The MPS maintains a &#8220;summary&#8221; of the zones
pointed to by all the pointers in a segment from previous scans.</p>
<p>So, once the MPS has decided what to condemn, it can quickly eliminate
all segments which definitely do not point to anything in those zones.
This avoids a large amount of scanning. It is an implementation of a
<a class="reference internal" href="../glossary/r.html#term-remembered-set"><em class="xref std std-term">remembered set</em></a>, though it is unlike that in most other
collectors.</p>
<p>In addition, the <a class="reference internal" href="../glossary/f.html#term-fix"><em class="xref std std-term">fix</em></a> operation can quickly ignore pointers to
the wrong zones. This is called the &#8220;zone check&#8221; and is a
<a class="reference internal" href="../glossary/b.html#term-bibop"><em class="xref std std-term">BIBOP</em></a> technique.</p>
<p>Even if a pointer passes the zone check, it may still not point to a
segment containing condemned objects. The next stage of the fix
operation is to look up the segment pointed to by the pointer and see
if it was condemned. This is a fast lookup.</p>
<p>After that, each pool class must decide whether the pointer is to a
condemned object and do something to preserve it. This code is still
critical. The MPS will have tried to condemn objects that are dead,
but those objects are still likely to be in segments with other
objects that must be preserved. The pool class fix method must quickly
distinguish between them.</p>
<p>Furthermore, many objects will be preserved at least once in their
lifetime, so even the code that preserves an object needs to be highly
efficient. (Programs in languages like <a class="reference internal" href="../mmref/lang.html#term-ml"><em class="xref std std-term">ML</em></a> might not preserve
95% of their objects even once, but programs in many other languages
tend to preserve nearly all of theirs many times.)</p>
</div>
<div class="section" id="where-to-find-the-critical-path">
<h2>3.3. Where to find the critical path<a class="headerlink" href="#where-to-find-the-critical-path" title="Permalink to this headline"></a></h2>
<p>Very briefly, the critical path consists of five stages:</p>
<ol class="arabic">
<li><p class="first">The scanner, which iterates over pointers in objects. The MPS has
several internal scanners, but the most important ones will be the
<a class="reference internal" href="../glossary/s.html#term-scan-method"><em class="xref std std-term">scan methods</em></a> in the client program&#8217;s
<a class="reference internal" href="../glossary/o.html#term-object-format"><em class="xref std std-term">object formats</em></a>. See <a class="reference internal" href="scanning.html#topic-scanning"><em>Scanning</em></a>.</p>
</li>
<li><p class="first">The first-stage fix, which filters out pointers inline in the
scanner. This is implemented in the <a class="reference internal" href="scanning.html#MPS_FIX1" title="MPS_FIX1"><tt class="xref c c-func docutils literal"><span class="pre">MPS_FIX1()</span></tt></a> macro.</p>
</li>
<li><p class="first">The second-stage fix, which filters out pointers using general
information about segments. This is implemented by the
<a class="reference internal" href="scanning.html#MPS_FIX2" title="MPS_FIX2"><tt class="xref c c-func docutils literal"><span class="pre">MPS_FIX2()</span></tt></a> macro, which calls <tt class="docutils literal"><span class="pre">_mps_fix</span></tt> in <tt class="docutils literal"><span class="pre">trace.c</span></tt>.</p>
</li>
<li><p class="first">The third-stage fix, which filters out pointers using pool-specific
information. Implemented in pool class functions called <tt class="docutils literal"><span class="pre">AMCFix</span></tt>,
<tt class="docutils literal"><span class="pre">LOFix</span></tt>, and so on in <tt class="docutils literal"><span class="pre">pool*.c</span></tt>.</p>
</li>
<li><p class="first">Preserving the object, which might entail:</p>
<ul class="simple">
<li><a class="reference internal" href="../glossary/m.html#term-marking"><em class="xref std std-term">marking</em></a> it to prevent it being recycled; and/or</li>
<li><a class="reference internal" href="../glossary/c.html#term-copying-garbage-collection"><em class="xref std std-term">copying</em></a> it and updating the
original pointer (or just updating the pointer, if the object has
previously been copied); and/or</li>
<li>adding it to a queue of objects to be scanned later, if it
contains pointers.</li>
</ul>
<p>Found in or near the pool class fix functions.</p>
</li>
</ol>
</div>
<div class="section" id="the-format-scanner">
<h2>3.4. The format scanner<a class="headerlink" href="#the-format-scanner" title="Permalink to this headline"></a></h2>
<p>The critical path starts when an <a class="reference internal" href="../glossary/o.html#term-object-format"><em class="xref std std-term">object format&#8217;s</em></a> <a class="reference internal" href="../glossary/s.html#term-scan-method"><em class="xref std std-term">scan method</em></a> is called. That is a call from the MPS to
a client function of type <a class="reference internal" href="format.html#mps_fmt_scan_t" title="mps_fmt_scan_t"><tt class="xref c c-type docutils literal"><span class="pre">mps_fmt_scan_t</span></tt></a> registered with one
of the format creation functions. (See <a class="reference internal" href="format.html#topic-format"><em>Object formats</em></a>.)</p>
<p>Here is an example of part of a format scanner for scanning contiguous
runs of pointers, from <tt class="docutils literal"><span class="pre">fmtdy.c</span></tt>, the scanner for the <a class="reference external" href="http://opendylan.org/">Open Dylan</a> runtime:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="n">mps_res_t</span> <span class="nf">dylan_scan_contig</span><span class="p">(</span><span class="n">mps_ss_t</span> <span class="n">mps_ss</span><span class="p">,</span>
<span class="n">mps_addr_t</span> <span class="o">*</span><span class="n">base</span><span class="p">,</span> <span class="n">mps_addr_t</span> <span class="o">*</span><span class="n">limit</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">mps_res_t</span> <span class="n">res</span><span class="p">;</span>
<span class="n">mps_addr_t</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span> <span class="cm">/* reference cursor */</span>
<span class="n">mps_addr_t</span> <span class="n">r</span><span class="p">;</span> <span class="cm">/* reference to be fixed */</span>
<span class="n">MPS_SCAN_BEGIN</span><span class="p">(</span><span class="n">mps_ss</span><span class="p">)</span> <span class="p">{</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">base</span><span class="p">;</span>
<span class="nl">loop:</span> <span class="k">if</span><span class="p">(</span><span class="n">p</span> <span class="o">&gt;=</span> <span class="n">limit</span><span class="p">)</span> <span class="k">goto</span> <span class="n">out</span><span class="p">;</span>
<span class="n">r</span> <span class="o">=</span> <span class="o">*</span><span class="n">p</span><span class="o">++</span><span class="p">;</span>
<span class="k">if</span><span class="p">(((</span><span class="n">mps_word_t</span><span class="p">)</span><span class="n">r</span><span class="o">&amp;</span><span class="mi">3</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="cm">/* pointers tagged with 0 */</span>
<span class="k">goto</span> <span class="n">loop</span><span class="p">;</span> <span class="cm">/* not a pointer */</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">MPS_FIX1</span><span class="p">(</span><span class="n">mps_ss</span><span class="p">,</span> <span class="n">r</span><span class="p">))</span> <span class="k">goto</span> <span class="n">loop</span><span class="p">;</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">MPS_FIX2</span><span class="p">(</span><span class="n">mps_ss</span><span class="p">,</span> <span class="n">p</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">res</span> <span class="o">==</span> <span class="n">MPS_RES_OK</span><span class="p">)</span> <span class="k">goto</span> <span class="n">loop</span><span class="p">;</span>
<span class="k">return</span> <span class="n">res</span><span class="p">;</span>
<span class="nl">out:</span> <span class="n">assert</span><span class="p">(</span><span class="n">p</span> <span class="o">==</span> <span class="n">limit</span><span class="p">);</span>
<span class="p">}</span> <span class="n">MPS_SCAN_END</span><span class="p">(</span><span class="n">mps_ss</span><span class="p">);</span>
<span class="k">return</span> <span class="n">MPS_RES_OK</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>(To help with understanding optimisation of this code, it&#8217;s written in a
pseudo-assembler style, with one line roughly corresponding to each
instruction of an idealized intermediate code.)</p>
<p>The MPS C interface provides macros to try to help optimise this code.
The first parameter, of type <a class="reference internal" href="scanning.html#mps_ss_t" title="mps_ss_t"><tt class="xref c c-type docutils literal"><span class="pre">mps_ss_t</span></tt></a>, is a <a class="reference internal" href="../glossary/s.html#term-scan-state"><em class="xref std std-term">scan
state</em></a> and contains data that is used to eliminate uninteresting
pointers now, and record information which will be used to reduce
scanning in future by maintaining the remembered set.</p>
<p>The macros <a class="reference internal" href="scanning.html#MPS_SCAN_BEGIN" title="MPS_SCAN_BEGIN"><tt class="xref c c-func docutils literal"><span class="pre">MPS_SCAN_BEGIN()</span></tt></a> and <a class="reference internal" href="scanning.html#MPS_SCAN_END" title="MPS_SCAN_END"><tt class="xref c c-func docutils literal"><span class="pre">MPS_SCAN_END()</span></tt></a> load
key data from the scan state into local variables, and hopefully into
processor registers. This avoids aliasing values that we know won&#8217;t
change when calls are made to <a class="reference internal" href="scanning.html#MPS_FIX2" title="MPS_FIX2"><tt class="xref c c-func docutils literal"><span class="pre">MPS_FIX2()</span></tt></a> later, and so allows
the compiler to keep the scan loop small and avoid unnecessary memory
references.</p>
<p>This scanner knows that words not ending in <tt class="docutils literal"><span class="pre">0b00</span></tt> aren&#8217;t pointers
to objects, so it eliminates them straight away. This is a <a class="reference internal" href="../glossary/t.html#term-tag"><em class="xref std std-term">tag</em></a>
chosen by the client program for its object representation.</p>
<p>Next, the pointer is tested using <a class="reference internal" href="scanning.html#MPS_FIX1" title="MPS_FIX1"><tt class="xref c c-func docutils literal"><span class="pre">MPS_FIX1()</span></tt></a>. This performs
fast tests on the pointer without using any other memory. In
particular, it does the &#8220;zone check&#8221; described above. If a pointer
fails these tests, it isn&#8217;t interesting and can be skipped. It is very
important to proceed to the next pointer as fast as possible in this
case.</p>
<p>Having passed these tests, we need to fix the pointer using other data
in memory, and possibly call the MPS to preserve the object. This is
what <a class="reference internal" href="scanning.html#MPS_FIX2" title="MPS_FIX2"><tt class="xref c c-func docutils literal"><span class="pre">MPS_FIX2()</span></tt></a> does. The important distinction here is that
<a class="reference internal" href="scanning.html#MPS_FIX2" title="MPS_FIX2"><tt class="xref c c-func docutils literal"><span class="pre">MPS_FIX2()</span></tt></a> can fail and return an error code, which must be
propagated without ado by returning from the scanner. Separating
<a class="reference internal" href="scanning.html#MPS_FIX1" title="MPS_FIX1"><tt class="xref c c-func docutils literal"><span class="pre">MPS_FIX1()</span></tt></a> from <a class="reference internal" href="scanning.html#MPS_FIX2" title="MPS_FIX2"><tt class="xref c c-func docutils literal"><span class="pre">MPS_FIX2()</span></tt></a> helps keep the error
handling code away from the tight loop with the zone check.</p>
<p>The macro/inline parts of the fix operation are referred to as &#8220;fix
stage 1&#8221; or &#8220;the first stage fix&#8221; in other documents and comments.</p>
<p>If these inline checks pass, <tt class="docutils literal"><span class="pre">_mps_fix2</span></tt> is called. If the MPS has
been built as a separate object file or library, this is where the
function call out of the scan loop happens. Since version 1.110 of the
MPS, we encourage clients to compile the MPS in the same translation
unit as their format code, so that the compiler can be intelligent
about inlining parts of <tt class="docutils literal"><span class="pre">_mps_fix2</span></tt> in the format scanner. See <a class="reference internal" href="../guide/build.html#guide-build"><em>Building the Memory Pool System</em></a>.</p>
</div>
<div class="section" id="the-second-stage-fix">
<h2>3.5. The second stage fix<a class="headerlink" href="#the-second-stage-fix" title="Permalink to this headline"></a></h2>
<p>If a pointer gets past the first-stage fix filters, it is passed to
<tt class="docutils literal"><span class="pre">_mps_fix2</span></tt>, the &#8220;second stage fix&#8221;. The second stage can filter out
yet more pointers using information about segments before it has to
consult the pool class.</p>
<p>The first test applied is the &#8220;tract test&#8221;. The MPS looks up the tract
containing the address in the tract table, which is a simple linear
table indexed by the address shifted: a kind of flat <a class="reference internal" href="../glossary/p.html#term-page-table"><em class="xref std std-term">page
table</em></a>.</p>
<p>Note that if the arena has been extended, the tract table becomes less
simple, and this test may involved looking in more than one table.
This will cause a considerable slow-down in garbage collection
scanning. This is the reason that it&#8217;s important to reserve an address
space that is several times larger than (a good estimate of) your peak
memory usage when you initialize a <a class="reference internal" href="../glossary/v.html#term-virtual-memory-arena"><em class="xref std std-term">virtual memory arena</em></a>.</p>
<p>The pointer might not even be in the arena (and so not in any tract).
The first stage fix doesn&#8217;t guarantee it. So we eliminate any pointers
not in the arena at this stage.</p>
<p>If the pointer is in an allocated tract, then the table also contains
a cache of the &#8220;white set&#8221;, the set of garbage collection traces for
which the tract is &#8220;interesting&#8221;. If a tract isn&#8217;t interesting, then
we know that it contains no condemned objects, and we can filter out
the pointer.</p>
<p>If the tract is interesting them it&#8217;s part of a segment containing
objects that have been condemned. The MPM can&#8217;t know anything about
the internal layout of the segment, so at this point we dispatch to
the third stage fix.</p>
<p>This dispatch is slightly subtle. We have a cache of the function to
dispatch to in the <a class="reference internal" href="../glossary/s.html#term-scan-state"><em class="xref std std-term">scan state</em></a>, which has recently been looked
at and is with luck still in the processor cache. The reason there is
a dispatch at all is to allow for a fast changeover to emergency
garbage collection, or overriding of garbage collection with extra
operations. Those are beyond the scope of this document. Normally,
<tt class="docutils literal"><span class="pre">ss-&gt;fix</span></tt> points at <tt class="docutils literal"><span class="pre">PoolFix</span></tt>, and we rely somewhat on modern
processor <a class="reference external" href="https://en.wikipedia.org/wiki/Branch_target_predictor">branch target prediction</a>. <tt class="docutils literal"><span class="pre">PoolFix</span></tt>
is passed the pool, which is fetched from the tract table entry, and
that should be in the cache.</p>
<p><tt class="docutils literal"><span class="pre">PoolFix</span></tt> itself dispatches to the pool class. Normally, a dispatch
to a pool class would indirect through the pool class object. That
would be a double indirection from the tract, so instead we have a
cache of the pool&#8217;s fix method in the pool object. This also allows a
pool class to vary its fix method per pool instance, a fact that is
exploited to optimize fixing in <a class="reference internal" href="../pool/amc.html#pool-amc"><em>AMC (Automatic Mostly-Copying)</em></a>, depending on what
kind of object format it is managing.</p>
</div>
<div class="section" id="the-third-stage-fix-in-the-pool-class">
<h2>3.6. The third stage fix in the pool class<a class="headerlink" href="#the-third-stage-fix-in-the-pool-class" title="Permalink to this headline"></a></h2>
<p>The final stage of fixing is entirely dependent on the <a class="reference internal" href="../glossary/p.html#term-pool-class"><em class="xref std std-term">pool
class</em></a>. The Memory Pool Manager can&#8217;t, in general, know how the
objects within a pool are arranged, so this is pool class specific
code.</p>
<p>Furthermore, the pool class must make decisions based on the
<a class="reference internal" href="../glossary/r.html#term-rank"><em class="xref std std-term">reference rank</em></a> of the pointer. If a pointer is
<a class="reference internal" href="../glossary/a.html#term-ambiguous-reference"><em class="xref std std-term">ambiguous</em></a> then it can&#8217;t be changed, so
even a <a class="reference internal" href="../glossary/c.html#term-copying-garbage-collection"><em class="xref std std-term">copying</em></a> pool class can&#8217;t
move an object. On the other hand, if the pointer is <a class="reference internal" href="../glossary/w.html#term-weak-reference-1"><em class="xref std std-term">weak</em></a> then the pool fix method shouldn&#8217;t preserve the object
at all, even if it&#8217;s condemned.</p>
<p>The exact details of the logic that the pool fix must implement in
order to co-operate with the MPM and other pools are beyond the scope
of this document, which is about the critical path. Since it is on the
critical path, it&#8217;s important that whatever the pool fix does is
simple and fast and returns to scanning as soon as possible.</p>
<p>The first step, though, is to further filter out pointers which aren&#8217;t
to objects, if that&#8217;s its policy. Then, it may preserve the object,
according to its policy, and possibly ensure that the object gets
scanned at some point in the future, if it contains more pointers.</p>
<p>If the object is moved to preserve it (for instance, if the pool class
implements copying garbage collection), or was already moved when
fixing a previous reference to it, the reference being fixed must be
updated (this is the origin of the term &#8220;fix&#8221;).</p>
<p>As a simple example, <tt class="docutils literal"><span class="pre">LOFix</span></tt> is the pool fix method for the
<a class="reference internal" href="../pool/lo.html#pool-lo"><em>LO (Leaf Object)</em></a> pool class. It implements a <a class="reference internal" href="../glossary/m.html#term-marking"><em class="xref std std-term">marking</em></a> garbage
collector, and does not have to worry about scanning preserved objects
because it is used to store objects that don&#8217;t contain pointers. (It
is used in compiler run-time systems to store binary data such as
character strings, thus avoiding any scanning, decoding, or remembered
set overhead for them.)</p>
<p><tt class="docutils literal"><span class="pre">LOFix</span></tt> filters any ambiguous pointers that aren&#8217;t aligned, since
they can&#8217;t point to objects it allocated. Otherwise it subtracts the
segment base address and shifts the result to get an index into a mark
bit table. If the object wasn&#8217;t marked and the pointer is weak, then
it sets the pointer to zero, since the object is about to be recycled.
Otherwise, the mark bit is set, which preserves the object from
recycling when <tt class="docutils literal"><span class="pre">LOReclaim</span></tt> is called later on. <tt class="docutils literal"><span class="pre">LOFix</span></tt> illustrates
about the minimum and most efficient thing a pool fix method can do.</p>
</div>
<div class="section" id="other-considerations">
<h2>3.7. Other considerations<a class="headerlink" href="#other-considerations" title="Permalink to this headline"></a></h2>
<p>So far this document has described the ways in which the garbage
collector is designed around optimising the critical path. There are a
few other things that the MPS does that are important.</p>
<p>Firstly, inlining is very important. The first stage fix is inlined
into the format scanner by being implemented in macros in <tt class="docutils literal"><span class="pre">mps.h</span></tt>.
And to get even better inlining, we recommend that the whole MPS is
compiled in a single translation unit with the client format and that
strong global optimisation is applied. See <a class="reference internal" href="../guide/build.html#guide-build"><em>Building the Memory Pool System</em></a>.</p>
<p>Secondly, we are very careful with code annotations on the critical
path. Assertions, statistics, and telemetry are all disabled on the
critical path in <a class="reference internal" href="../glossary/h.html#term-hot"><em class="xref std std-term">hot</em></a> (production) builds. (In fact, it&#8217;s
because the critical path is critical that we can afford to leave
annotations switched on elsewhere.)</p>
<p>Last, but by no means least, we pay a lot of brainpower and
measurement to the critical path, and are very very careful about
changing it. Code review around the critical path is especially
vigilant.</p>
<p>And we write long documents about it.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/logo.png" alt="Logo"/>
</a></p>
<h3><a href="../index.html">Table Of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">3. The critical path</a><ul>
<li><a class="reference internal" href="#what-makes-the-critical-path-critical">3.1. What makes the critical path critical</a></li>
<li><a class="reference internal" href="#how-the-mps-avoids-scanning-and-fixing">3.2. How the MPS avoids scanning and fixing</a></li>
<li><a class="reference internal" href="#where-to-find-the-critical-path">3.3. Where to find the critical path</a></li>
<li><a class="reference internal" href="#the-format-scanner">3.4. The format scanner</a></li>
<li><a class="reference internal" href="#the-second-stage-fix">3.5. The second stage fix</a></li>
<li><a class="reference internal" href="#the-third-stage-fix-in-the-pool-class">3.6. The third stage fix in the pool class</a></li>
<li><a class="reference internal" href="#other-considerations">3.7. Other considerations</a></li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="platform.html"
title="previous chapter">2. Platforms</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="../mmref/index.html"
title="next chapter">Introduction to memory management</a></p><h4>Contact us</h4>
<p class="topless"><a href="mailto:mps-questions@ravenbrook.com">mps-questions@ravenbrook.com</a></p>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../mmref/index.html" title="Introduction to memory management"
>next</a> |</li>
<li class="right" >
<a href="platform.html" title="2. Platforms"
>previous</a> |</li>
<li><a href="../index.html">Memory Pool System 1.111.0 documentation</a> &raquo;</li>
<li><a href="internals.html" >Internals</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2012, Ravenbrook Limited.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>