mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-19 19:37:58 +00:00
332 lines
No EOL
21 KiB
HTML
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 — 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> »</li>
|
|
<li><a href="index.html" accesskey="U">Introduction to memory management</a> »</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’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’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’t provide the
|
|
collector with information about the data types, and the collector
|
|
cannot therefore determine what is a pointer and what isn’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’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—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 “one” or “many” references. If a reference to an
|
|
object with “one” reference is removed, then the object can be
|
|
recycled. If an object has “many” 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’t change the total weight of all references, it doesn’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&view=status%3dopen&display=Job:Priority:Title&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> »</li>
|
|
<li><a href="index.html" >Introduction to memory management</a> »</li>
|
|
</ul>
|
|
</div>
|
|
<div class="footer">
|
|
© <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> |