emacs/mps/manual/html/mmref/recycle.html
Gareth Rees 06057a4d52 Bring html up to date.
Copied from Perforce
 Change: 181168
 ServerID: perforce.ravenbrook.com
2013-03-18 15:13:54 +00:00

332 lines
No EOL
21 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. Recycling techniques &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="Introduction to memory management" href="index.html" />
<link rel="next" title="4. Memory management in various languages" href="lang.html" />
<link rel="prev" title="2. Allocation techniques" href="alloc.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="lang.html" title="4. Memory management in various languages"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="alloc.html" title="2. Allocation techniques"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">Memory Pool System 1.111.0 documentation</a> &raquo;</li>
<li><a href="index.html" accesskey="U">Introduction to memory management</a> &raquo;</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body">
<div class="section" id="recycling-techniques">
<span id="mmref-recycle"></span><h1>3. Recycling techniques<a class="headerlink" href="#recycling-techniques" title="Permalink to this headline"></a></h1>
<p>There are many ways for automatic memory managers to determine what
memory is no longer required. In the main, garbage collection relies
on determining which blocks are not pointed to by any program
variables. Some of the techniques for doing this are described briefly
below, but there are many potential pitfalls, and many possible
refinements. These techniques can often be used in combination.</p>
<div class="section" id="tracing-collectors">
<h2>3.1. Tracing collectors<a class="headerlink" href="#tracing-collectors" title="Permalink to this headline"></a></h2>
<p>Automatic memory managers that follow pointers to determine which
blocks of memory are <a class="reference internal" href="../glossary/r.html#term-reachable"><em class="xref std std-term">reachable</em></a> from program variables (known
as the <a class="reference internal" href="../glossary/r.html#term-root-set"><em class="xref std std-term">root set</em></a>) are known as <em class="dfn">tracing</em> collectors. The
classic example is the mark-sweep collector.</p>
<div class="section" id="mark-sweep-collection">
<h3>3.1.1. Mark-sweep collection<a class="headerlink" href="#mark-sweep-collection" title="Permalink to this headline"></a></h3>
<p>In a <a class="reference internal" href="../glossary/m.html#term-mark-sweep"><em class="xref std std-term">mark-sweep</em></a> collection, the collector first examines the
program variables; any blocks of memory pointed to are added to a list
of blocks to be examined. For each block on that list, it sets a flag
(the mark) on the block to show that it is still required, and also
that it has been processed. It also adds to the list any blocks
pointed to by that block that have not yet been marked. In this way,
all blocks that can be reached by the program are marked.</p>
<p>In the second phase, the collector <em>sweeps</em> all allocated memory,
searching for blocks that have not been marked. If it finds any, it
returns them to the allocator for reuse.</p>
<div class="figure align-center">
<img alt="Diagram: Five memory blocks, three of which are reachable from program variables." src="../_images/mark-sweep.svg" /><p class="caption">Five memory blocks, three of which are reachable from program variables.</p>
</div>
<p>In the diagram above, block 1 is directly accessible from a program
variable, and blocks 2 and 3 are indirectly accessible. Blocks 4 and 5
cannot be reached by the program. The first step would mark block 1,
and remember blocks 2 and 3 for later processing. The second step
would mark block 2. The third step would mark block 3, but wouldn&#8217;t
remember block 2 as it is already marked. The sweep phase would ignore
blocks 1, 2, and 3 because they are marked, but would recycle blocks 4
and 5.</p>
<p>The two drawbacks of simple mark-sweep collection are:</p>
<ul class="simple">
<li>it must scan the entire memory in use before any memory can be freed;</li>
<li>it must run to completion or, if interrupted, start again from scratch.</li>
</ul>
<p>If a system requires real-time or interactive response, then simple
mark-sweep collection may be unsuitable as it stands, but many more
sophisticated garbage collection algorithms are derived from this
technique.</p>
</div>
<div class="section" id="copying-collection">
<h3>3.1.2. Copying collection<a class="headerlink" href="#copying-collection" title="Permalink to this headline"></a></h3>
<p>After many memory blocks have been allocated and recycled, there are
two problems that typically occur:</p>
<ul class="simple">
<li>the memory in use is widely scattered in memory, causing poor
performance in the <a class="reference internal" href="../glossary/c.html#term-cache-1"><em class="xref std std-term">memory caches</em></a> or
<a class="reference internal" href="../glossary/v.html#term-virtual-memory"><em class="xref std std-term">virtual memory</em></a> systems of most modern computers (known as
poor <a class="reference internal" href="../glossary/l.html#term-locality-of-reference"><em class="xref std std-term">locality of reference</em></a>);</li>
<li>it becomes difficult to allocate large blocks because free memory is
divided into small pieces, separated by blocks in use (known as
<a class="reference internal" href="../glossary/e.html#term-external-fragmentation"><em class="xref std std-term">external fragmentation</em></a>).</li>
</ul>
<p>One technique that can solve both these problems is <a class="reference internal" href="../glossary/c.html#term-copying-garbage-collection"><em class="xref std std-term">copying
garbage collection</em></a>. A copying garbage collector may move allocated
blocks around in memory and adjust any references to them to point to
the new location. This is a very powerful technique and can be
combined with many other types of garbage collection, such as
mark-sweep collection.</p>
<p>The disadvantages of copying collection are:</p>
<ul class="simple">
<li>it is difficult to combine with <a class="reference internal" href="../glossary/i.html#term-incremental-garbage-collection"><em class="xref std std-term">incremental garbage
collection</em></a> (see below) because all references must be adjusted to
remain consistent;</li>
<li>it is difficult to combine with <a class="reference internal" href="../glossary/c.html#term-conservative-garbage-collection"><em class="xref std std-term">conservative garbage
collection</em></a> (see below) because references cannot be confidently
adjusted;</li>
<li>extra storage is required while both new and old copies of an object
exist;</li>
<li>copying data takes extra time (proportional to the amount of
<a class="reference internal" href="../glossary/l.html#term-live"><em class="xref std std-term">live</em></a> data).</li>
</ul>
</div>
<div class="section" id="incremental-collection">
<h3>3.1.3. Incremental collection<a class="headerlink" href="#incremental-collection" title="Permalink to this headline"></a></h3>
<p>Older garbage collection algorithms relied on being able to start
collection and continue working until the collection was complete,
without interruption. This makes many interactive systems pause during
collection, and makes the presence of garbage collection obtrusive.</p>
<p>Fortunately, there are modern techniques (known as <a class="reference internal" href="../glossary/i.html#term-incremental-garbage-collection"><em class="xref std std-term">incremental
garbage collection</em></a>) to allow garbage collection to be performed in a
series of small steps while the program is never stopped for long. In
this context, the program that uses and modifies the blocks is
sometimes known as the <a class="reference internal" href="../glossary/m.html#term-mutator"><em class="xref std std-term">mutator</em></a>. While the collector is trying
to determine which blocks of memory are reachable by the mutator, the
mutator is busily allocating new blocks, modifying old blocks, and
changing the set of blocks it is actually looking at.</p>
<p>Incremental collection is usually achieved with either the cooperation
of the memory hardware or the mutator; this ensures that, whenever
memory in crucial locations is accessed, a small amount of necessary
bookkeeping is performed to keep the collector&#8217;s data structures
correct.</p>
</div>
<div class="section" id="conservative-garbage-collection">
<h3>3.1.4. Conservative garbage collection<a class="headerlink" href="#conservative-garbage-collection" title="Permalink to this headline"></a></h3>
<p>Although garbage collection was first invented in 1958, many languages
have been designed and implemented without the possibility of garbage
collection in mind. It is usually difficult to add normal garbage
collection to such a system, but there is a technique, known as
<a class="reference internal" href="../glossary/c.html#term-conservative-garbage-collection"><em class="xref std std-term">conservative garbage collection</em></a>, that can be used.</p>
<p>The usual problem with such a language is that it doesn&#8217;t provide the
collector with information about the data types, and the collector
cannot therefore determine what is a pointer and what isn&#8217;t. A
conservative collector assumes that anything <em>might</em> be a pointer. It
regards any data value that looks like a pointer to or into a block of
allocated memory as preventing the recycling of that block.</p>
<p>Note that, because the collector does not know for certain which
memory locations contain pointers, it cannot readily be combined with
copying garbage collection. Copying collection needs to know where
pointers are in order to update them when blocks are moved.</p>
<p>You might think that conservative garbage collection could easily
perform quite poorly, leaving a lot of garbage uncollected. In
practice, it does quite well, and there are refinements that improve
matters further.</p>
</div>
</div>
<div class="section" id="reference-counts">
<h2>3.2. Reference counts<a class="headerlink" href="#reference-counts" title="Permalink to this headline"></a></h2>
<p>A reference count is a count of how many <a class="reference internal" href="../glossary/r.html#term-reference"><em class="xref std std-term">references</em></a> (that is,
pointers) there are to a particular memory block from other blocks. It
is used as the basis for some automatic recycling techniques that do
not rely on tracing.</p>
<div class="section" id="simple-reference-counting">
<h3>3.2.1. Simple reference counting<a class="headerlink" href="#simple-reference-counting" title="Permalink to this headline"></a></h3>
<p>In a simple <a class="reference internal" href="../glossary/r.html#term-reference-counting"><em class="xref std std-term">reference counting</em></a> system, a reference count is
kept for each <a class="reference internal" href="../glossary/o.html#term-object"><em class="xref std std-term">object</em></a>. This count is incremented for each new
reference, and is decremented if a reference is overwritten, or if the
referring object is recycled. If a reference count falls to zero, then
the object is no longer required and can be recycled.</p>
<p>Reference counting is frequently chosen as an automatic memory
management strategy because it seems simple to implement using
<a class="reference internal" href="../glossary/m.html#term-manual-memory-management"><em class="xref std std-term">manual memory management</em></a> primitives. However, it is hard to
implement efficiently because of the cost of updating the counts. It
is also hard to implement reliably, because the standard technique
cannot reclaim objects connected in a loop. In many cases, it is an
inappropriate solution, and it would be preferable to use
<a class="reference internal" href="../glossary/t.html#term-tracing-garbage-collection"><em class="xref std std-term">tracing garbage collection</em></a> instead.</p>
<p>Reference counting is most useful in situations where it can be
guaranteed that there will be no loops and where modifications to the
reference structure are comparatively infrequent. These circumstances
can occur in some types of database structure and some file systems.
Reference counting may also be useful if it is important that objects
are recycled promptly, such as in systems with tight memory
constraints.</p>
</div>
<div class="section" id="deferred-reference-counting">
<h3>3.2.2. Deferred reference counting<a class="headerlink" href="#deferred-reference-counting" title="Permalink to this headline"></a></h3>
<p>The performance of reference counting can be improved if not all
references are taken into account. In one important technique, known
as <a class="reference internal" href="../glossary/d.html#term-deferred-reference-counting"><em class="xref std std-term">deferred reference counting</em></a>, only references from other
objects are counted, and references from program variables are
ignored. Since most of the references to the object are likely to be
from local variables, this can substantially reduce the overhead of
keeping the counts up to date. An object cannot be reclaimed as soon
as its count has dropped to zero, because there might still be a
reference to it from a program variable. Instead, the program
variables (including the <a class="reference internal" href="../glossary/c.html#term-control-stack"><em class="xref std std-term">control stack</em></a>) are periodically
<a class="reference internal" href="../glossary/s.html#term-scan"><em class="xref std std-term">scanned</em></a>, and any objects which are not referenced from
there and which have zero count are reclaimed.</p>
<p>Deferred reference counting cannot normally be used unless it is
directly supported by the compiler. It&#8217;s more common for modern
compilers to support tracing garbage collectors instead, because they
can reclaim loops. Deferred reference counting may still be useful for
its promptness&#8212;but that is limited by the frequency of scanning the
program variables.</p>
</div>
<div class="section" id="one-bit-reference-counting">
<h3>3.2.3. One-bit reference counting<a class="headerlink" href="#one-bit-reference-counting" title="Permalink to this headline"></a></h3>
<p>Another variation on reference counting, known as the <a class="reference internal" href="../glossary/o.html#term-one-bit-reference-count"><em class="xref std std-term">one-bit
reference count</em></a>, uses a single bit flag to indicate whether each
object has either &#8220;one&#8221; or &#8220;many&#8221; references. If a reference to an
object with &#8220;one&#8221; reference is removed, then the object can be
recycled. If an object has &#8220;many&#8221; references, then removing references
does not change this, and that object will never be recycled. It is
possible to store the flag as part of the <em>pointer</em> to the object, so
no additional space is required in each object to store the count.
One-bit reference counting is effective in practice because most
actual objects have a reference count of one.</p>
</div>
<div class="section" id="weighted-reference-counting">
<h3>3.2.4. Weighted reference counting<a class="headerlink" href="#weighted-reference-counting" title="Permalink to this headline"></a></h3>
<p>Reference counting is often used for tracking inter-process references for <a class="reference internal" href="../glossary/d.html#term-distributed-garbage-collection"><em class="xref std std-term">distributed garbage collection</em></a>. This fails to collect objects in separate processes if they have looped references, but tracing collectors are usually too inefficient as inter-process tracing entails much communication between processes. Within a process, tracing collectors are often used for local recycling of memory.</p>
<p>Many distributed collectors use a technique called <a class="reference internal" href="../glossary/w.html#term-weighted-reference-counting"><em class="xref std std-term">weighted
reference counting</em></a>, which reduces the level of communication even
further. Each time a reference is copied, the weight of the reference
is shared between the new and the old copies. Since this operation
doesn&#8217;t change the total weight of all references, it doesn&#8217;t require
any communication with the object. Communication is only required when
references are deleted.</p>
</div>
</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. Recycling techniques</a><ul>
<li><a class="reference internal" href="#tracing-collectors">3.1. Tracing collectors</a><ul>
<li><a class="reference internal" href="#mark-sweep-collection">3.1.1. Mark-sweep collection</a></li>
<li><a class="reference internal" href="#copying-collection">3.1.2. Copying collection</a></li>
<li><a class="reference internal" href="#incremental-collection">3.1.3. Incremental collection</a></li>
<li><a class="reference internal" href="#conservative-garbage-collection">3.1.4. Conservative garbage collection</a></li>
</ul>
</li>
<li><a class="reference internal" href="#reference-counts">3.2. Reference counts</a><ul>
<li><a class="reference internal" href="#simple-reference-counting">3.2.1. Simple reference counting</a></li>
<li><a class="reference internal" href="#deferred-reference-counting">3.2.2. Deferred reference counting</a></li>
<li><a class="reference internal" href="#one-bit-reference-counting">3.2.3. One-bit reference counting</a></li>
<li><a class="reference internal" href="#weighted-reference-counting">3.2.4. Weighted reference counting</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h4>Previous topic</h4>
<p class="topless"><a href="alloc.html"
title="previous chapter">2. Allocation techniques</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="lang.html"
title="next chapter">4. Memory management in various languages</a></p><h4>Downloads</h4>
<p class="topless">
<a href="http://www.ravenbrook.com/project/mps/release/1.111.0/">MPS Kit release 1.111.0</a><br>
<a href="http://www.ravenbrook.com/project/mps/release/">All MPS Kit releases</a>
</p>
<h4>Issues</h4>
<p class="topless">
<a href="http://www.ravenbrook.com/project/mps/issue/?action=list&amp;view=status%3dopen&amp;display=Job:Priority:Title&amp;sort=Priority">Known issues</a><br>
<a href="http://www.ravenbrook.com/project/mps/issue/?action=fixed&release_fixed=1.111.0">Issues fixed in release 1.111.0</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="lang.html" title="4. Memory management in various languages"
>next</a> |</li>
<li class="right" >
<a href="alloc.html" title="2. Allocation techniques"
>previous</a> |</li>
<li><a href="../index.html">Memory Pool System 1.111.0 documentation</a> &raquo;</li>
<li><a href="index.html" >Introduction to memory management</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2013, Ravenbrook Limited.
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
</div>
</body>
</html>