emacs.d/clones/lisp/docs.racket-lang.org/guide/performance.html

348 lines
149 KiB
HTML
Raw Normal View History

2022-08-15 11:06:56 +02:00
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"/><meta name="viewport" content="width=device-width, initial-scale=0.8"/><title>19&nbsp;Performance</title><link rel="stylesheet" type="text/css" href="../scribble.css" title="default"/><link rel="stylesheet" type="text/css" href="../racket.css" title="default"/><link rel="stylesheet" type="text/css" href="../manual-style.css" title="default"/><link rel="stylesheet" type="text/css" href="../manual-racket.css" title="default"/><link rel="stylesheet" type="text/css" href="../manual-racket.css" title="default"/><link rel="stylesheet" type="text/css" href="../doc-site.css" title="default"/><script type="text/javascript" src="../scribble-common.js"></script><script type="text/javascript" src="../manual-racket.js"></script><script type="text/javascript" src="../manual-racket.js"></script><script type="text/javascript" src="../doc-site.js"></script><script type="text/javascript" src="../local-redirect/local-redirect.js"></script><script type="text/javascript" src="../local-redirect/local-user-redirect.js"></script><!--[if IE 6]><style type="text/css">.SIEHidden { overflow: hidden; }</style><![endif]--></head><body id="doc-racket-lang-org"><div class="tocset"><div class="tocview"><div class="tocviewlist tocviewlisttopspace"><div class="tocviewtitle"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,&quot;tocview_0&quot;);">&#9660;</a></td><td></td><td><a href="index.html" class="tocviewlink" data-pltdoc="x">The Racket Guide</a></td></tr></table></div><div class="tocviewsublisttop" style="display: block;" id="tocview_0"><table cellspacing="0" cellpadding="0"><tr><td align="right">1&nbsp;</td><td><a href="intro.html" class="tocviewlink" data-pltdoc="x">Welcome to Racket</a></td></tr><tr><td align="right">2&nbsp;</td><td><a href="to-scheme.html" class="tocviewlink" data-pltdoc="x">Racket Essentials</a></td></tr><tr><td align="right">3&nbsp;</td><td><a href="datatypes.html" class="tocviewlink" data-pltdoc="x">Built-<wbr></wbr>In Datatypes</a></td></tr><tr><td align="right">4&nbsp;</td><td><a href="scheme-forms.html" class="tocviewlink" data-pltdoc="x">Expressions and Definitions</a></td></tr><tr><td align="right">5&nbsp;</td><td><a href="define-struct.html" class="tocviewlink" data-pltdoc="x">Programmer-<wbr></wbr>Defined Datatypes</a></td></tr><tr><td align="right">6&nbsp;</td><td><a href="modules.html" class="tocviewlink" data-pltdoc="x">Modules</a></td></tr><tr><td align="right">7&nbsp;</td><td><a href="contracts.html" class="tocviewlink" data-pltdoc="x">Contracts</a></td></tr><tr><td align="right">8&nbsp;</td><td><a href="i_o.html" class="tocviewlink" data-pltdoc="x">Input and Output</a></td></tr><tr><td align="right">9&nbsp;</td><td><a href="regexp.html" class="tocviewlink" data-pltdoc="x">Regular Expressions</a></td></tr><tr><td align="right">10&nbsp;</td><td><a href="control.html" class="tocviewlink" data-pltdoc="x">Exceptions and Control</a></td></tr><tr><td align="right">11&nbsp;</td><td><a href="for.html" class="tocviewlink" data-pltdoc="x">Iterations and Comprehensions</a></td></tr><tr><td align="right">12&nbsp;</td><td><a href="match.html" class="tocviewlink" data-pltdoc="x">Pattern Matching</a></td></tr><tr><td align="right">13&nbsp;</td><td><a href="classes.html" class="tocviewlink" data-pltdoc="x">Classes and Objects</a></td></tr><tr><td align="right">14&nbsp;</td><td><a href="units.html" class="tocviewlink" data-pltdoc="x">Units</a></td></tr><tr><td align="right">15&nbsp;</td><td><a href="reflection.html" class="tocviewlink" data-pltdoc="x">Reflection and Dynamic Evaluation</a></td></tr><tr><td align="right">16&nbsp;</td><td><a href="macros.html" class="tocviewlink" data-pltdoc="x">Macros</a></td></tr><tr><td align="right">17&nbsp;</td><td><a href="languages.html" class="tocviewlink" data-pltdoc="x">Creating Languages</a></td></tr><tr><td align="right">18&nbsp;</td><td><a href="concurrency.html" class="tocviewlink" data-
everything and the cost of nothing.&rdquo; A Racket programmer knows, for
example, that a <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span> anywhere in a program produces a value
that is closed over its lexical environment&#8212;<wbr></wbr>but how much does
allocating that value cost? While most programmers have a reasonable
grasp of the cost of various operations and data structures at the
machine level, the gap between the Racket language model and the
underlying computing machinery can be quite large.</p><p>In this chapter, we narrow the gap by explaining details of the
Racket compiler and runtime system and how they affect the runtime
and memory performance of Racket code.</p><h4 x-source-module="(lib &quot;scribblings/guide/guide.scrbl&quot;)" x-source-pkg="racket-doc" x-part-tag="&quot;DrRacket-perf&quot;">19.1<tt>&nbsp;</tt><a name="(part._.Dr.Racket-perf)"></a>Performance in DrRacket</h4><p>By default, DrRacket instruments programs for debugging, and
debugging instrumentation (provided by the
<a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=errortrace&amp;rel=index.html&amp;version=8.6" class="Sq" data-pltdoc="x">Errortrace: Debugging and Profiling</a>
library) can significantly degrade performance for
some programs. Even when debugging is disabled through the
<span class="ssansserif">Choose Language...</span> dialog&rsquo;s <span class="ssansserif">Show Details</span> panel,
the <span class="ssansserif">Preserve stacktrace</span> checkbox is clicked by default,
which also affects performance. Disabling debugging and stacktrace
preservation provides performance results that are more consistent
with running in plain <span class="stt">racket</span>.</p><p>Even so, DrRacket and programs developed within DrRacket use the same
Racket virtual machine, so garbage collection times (see
<a href="performance.html#%28part._gc-perf%29" data-pltdoc="x">Memory Management</a>) may be longer in DrRacket than when a program is
run by itself, and DrRacket threads may impede execution of program
threads. <span style="font-weight: bold">For the most reliable timing results for a program, run in
plain <span class="stt">racket</span> instead of in the DrRacket development environment.</span>
Non-interactive mode should be used instead of the
<a href="intro.html#%28tech._repl%29" class="techoutside" data-pltdoc="x"><span class="techinside">REPL</span></a> to benefit from the module system. See
<a href="performance.html#%28part._modules-performance%29" data-pltdoc="x">Modules and Performance</a> for details.</p><h4 x-source-module="(lib &quot;scribblings/guide/guide.scrbl&quot;)" x-source-pkg="racket-doc" x-part-tag="&quot;virtual-machines&quot;">19.2<tt>&nbsp;</tt><a name="(part._virtual-machines)"></a>Racket Virtual Machine Implementations</h4><p>Racket is available in two implementations, <a name="(tech._c)"></a><span style="font-style: italic">CS</span> and
<a name="(tech._bc)"></a><span style="font-style: italic">BC</span>:</p><ul><li><p><a href="performance.html#%28tech._c%29" class="techoutside" data-pltdoc="x"><span class="techinside">CS</span></a> is the current default implementation. It is
a newer implementation that builds on
<a href="https://www.scheme.com/">Chez Scheme</a> as its core
virtual machine. This implementation performs better than
the <a href="performance.html#%28tech._bc%29" class="techoutside" data-pltdoc="x"><span class="techinside">BC</span></a> implementation for most programs.</p><p>For this implementation, <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=runtime.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._system-type%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">system-type</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">vm</span><span class="RktPn">)</span> reports
<span class="RktVal">'</span><span class="RktVal">chez-scheme</span> and <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=runtime.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._system-type%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">system-type</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">gc</span><span class="RktPn">)</span> reports
<span class="RktVal">'</span><span class="RktVal">cs</span>.</p></li><li><p><a href="performance.html#%28tech._bc%29" class="techoutside" data-pltdoc="x"><span class="techinside">BC</span></a> is an older implementation, and was the default until version 8.0.
The implementation features a compiler and runtime written in C,
with a precise garbage collector and a just-in-time compiler (JIT)
on most platforms.</p><p>For this implementation, <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=runtime.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._system-type%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">system-type</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">vm</span><span class="RktPn">)</span> reports
<span class="RktVal">'</span><span class="RktVal">racket</span>.</p><p>The BC implementation itself has two variants, <a name="(tech._3m)"></a><span style="font-style: italic">3m</span> and
<a name="(tech._cgc)"></a><span style="font-style: italic">CGC</span>:</p><ul><li><p><a href="performance.html#%28tech._3m%29" class="techoutside" data-pltdoc="x"><span class="techinside">3m</span></a> is the normal BC variant with a precise
garbage collector.</p><p>For this variant, <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=runtime.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._system-type%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">system-type</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">gc</span><span class="RktPn">)</span> reports
<span class="RktVal">'</span><span class="RktVal">3m</span>.</p></li><li><p><a href="performance.html#%28tech._cgc%29" class="techoutside" data-pltdoc="x"><span class="techinside">CGC</span></a> is the oldest variant. It&rsquo;s the same basic
implementation as <a href="performance.html#%28tech._3m%29" class="techoutside" data-pltdoc="x"><span class="techinside">3m</span></a> (i.e., the same virtual
machine), but compiled to rely on a &ldquo;conservative&rdquo;
garbage collector, which affects the way that Racket
interacts with C code. See <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=inside&amp;rel=overview.html%23%2528part._.C.G.C._versus._3m%2529&amp;version=8.6" class="Sq" data-pltdoc="x">CGC versus 3m</a> in <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=inside&amp;rel=index.html&amp;version=8.6" class="Sq" data-pltdoc="x">Inside: Racket C API</a> for more
information.</p><p>For this variant, <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=runtime.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._system-type%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">system-type</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">gc</span><span class="RktPn">)</span> reports
<span class="RktVal">'</span><span class="RktVal">cgc</span>.</p></li></ul></li></ul><p>In general, Racket programs should run the same in all variants.
Furthermore, the performance characteristics of Racket program should
be similar in the <a href="performance.html#%28tech._c%29" class="techoutside" data-pltdoc="x"><span class="techinside">CS</span></a> and <a href="performance.html#%28tech._bc%29" class="techoutside" data-pltdoc="x"><span class="techinside">BC</span></a> implementations. The cases
where a program may depend on the implementation will typically
involve interactions with foreign libraries; in particular, the Racket
C API described in <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=inside&amp;rel=index.html&amp;version=8.6" class="Sq" data-pltdoc="x">Inside: Racket C API</a> is different for the
<a href="performance.html#%28tech._c%29" class="techoutside" data-pltdoc="x"><span class="techinside">CS</span></a> implementation versus the <a href="performance.html#%28tech._bc%29" class="techoutside" data-pltdoc="x"><span class="techinside">BC</span></a> implementation.</p><h4 x-source-module="(lib &quot;scribblings/guide/guide.scrbl&quot;)" x-source-pkg="racket-doc" x-part-tag="&quot;JIT&quot;">19.3<tt>&nbsp;</tt><a name="(part._.J.I.T)"></a>Bytecode, Machine Code, and Just-in-Time (JIT) Compilers</h4><p>Every definition or expression to be evaluated by Racket is compiled
to an internal bytecode format, although &ldquo;bytecode&rdquo; may actually be
native machine code. In interactive mode, this compilation occurs
automatically and on-the-fly. Tools like <span class="stt">raco make</span> and
<span class="stt">raco setup</span> marshal compiled bytecode to a file, so that you do
not have to compile from source every time that you run a program.
See <a href="cmdline-tools.html#%28part._compile%29" data-pltdoc="x">Compilation and Configuration: <span class="stt">raco</span></a> for more information on generating
bytecode files.</p><p>The bytecode compiler applies all standard optimizations, such as
constant propagation, constant folding, inlining, and dead-code
elimination. For example, in an environment where <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span> has its
usual binding, the expression <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">x</span><span class="stt"> </span><span class="RktVal">1</span><span class="RktPn">]</span><span class="stt"> </span><span class="RktPn">[</span><span class="RktSym">y</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="stt"> </span><span class="RktPn">(</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktVal">4</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span><span class="stt"> </span><span class="RktVal">1</span><span class="stt"> </span><span class="RktPn">(</span><span class="RktSym">y</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span> is compiled the same as the constant <span class="RktVal">5</span>.</p><p>For the <a href="performance.html#%28tech._c%29" class="techoutside" data-pltdoc="x"><span class="techinside">CS</span></a> implementation of Racket, the main bytecode format
is non-portable machine code. For the <a href="performance.html#%28tech._bc%29" class="techoutside" data-pltdoc="x"><span class="techinside">BC</span></a> implementation of
Racket, bytecode is portable in the sense that it is
machine-independent. Setting <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=eval.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._current-compile-target-machine%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">current-compile-target-machine</a></span>
to <span class="RktVal">#f</span> selects a separate machine-independent and
variant-independent format on all Racket implementations, but running
code in that format requires an additional internal conversion step to
the implementation&rsquo;s main bytecode format.</p><p>Machine-independent bytecode for the <a href="performance.html#%28tech._bc%29" class="techoutside" data-pltdoc="x"><span class="techinside">BC</span></a> implementation is further
compiled to native code via a <a name="(tech._just._in._time)"></a><span style="font-style: italic">just-in-time</span> or <a name="(tech._jit)"></a><span style="font-style: italic">JIT</span>
compiler. The <a href="performance.html#%28tech._jit%29" class="techoutside" data-pltdoc="x"><span class="techinside">JIT</span></a> compiler substantially speeds programs that
execute tight loops, arithmetic on small integers, and arithmetic on
inexact real numbers. Currently, <a href="performance.html#%28tech._jit%29" class="techoutside" data-pltdoc="x"><span class="techinside">JIT</span></a> compilation is supported
for x86, x86_64 (a.k.a. AMD64), 32-bit ARM, and 32-bit PowerPC processors.
The <a href="performance.html#%28tech._jit%29" class="techoutside" data-pltdoc="x"><span class="techinside">JIT</span></a> compiler can be disabled via the
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=eval.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._eval-jit-enabled%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">eval-jit-enabled</a></span> parameter or the <span class="nobreak"><span class="stt">--no-jit</span></span>/<span class="nobreak"><span class="stt">-j</span></span>
command-line flag for <span class="stt">racket</span>. Setting <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=eval.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._eval-jit-enabled%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">eval-jit-enabled</a></span>
to <span class="RktVal">#f</span> has no effect on the <a href="performance.html#%28tech._c%29" class="techoutside" data-pltdoc="x"><span class="techinside">CS</span></a> implementation of Racket.</p><p>The <a href="performance.html#%28tech._jit%29" class="techoutside" data-pltdoc="x"><span class="techinside">JIT</span></a> compiler works incrementally as functions are applied,
but the <a href="performance.html#%28tech._jit%29" class="techoutside" data-pltdoc="x"><span class="techinside">JIT</span></a> compiler makes only limited use of run-time
information when compiling procedures, since the code for a given
module body or <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span> abstraction is compiled only once. The
<a href="performance.html#%28tech._jit%29" class="techoutside" data-pltdoc="x"><span class="techinside">JIT</span></a>&rsquo;s granularity of compilation is a single procedure body,
not counting the bodies of any lexically nested procedures. The
overhead for <a href="performance.html#%28tech._jit%29" class="techoutside" data-pltdoc="x"><span class="techinside">JIT</span></a> compilation is normally so small that it is
difficult to detect.</p><p>For information about viewing intermediate Racket code
representations, especially for the <a href="performance.html#%28tech._c%29" class="techoutside" data-pltdoc="x"><span class="techinside">CS</span></a> implementation, see
<a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=compiler.html%23%2528part._compiler-inspect%2529&amp;version=8.6" class="Sq" data-pltdoc="x">Inspecting Compiler Passes</a>.</p><h4 x-source-module="(lib &quot;scribblings/guide/guide.scrbl&quot;)" x-source-pkg="racket-doc" x-part-tag="&quot;modules-performance&quot;">19.4<tt>&nbsp;</tt><a name="(part._modules-performance)"></a>Modules and Performance</h4><p>The module system aids optimization by helping to ensure that
identifiers have the usual bindings. That is, the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span> provided
by <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=index.html&amp;version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket/base</span></a> can be recognized by the compiler and
inlined. In contrast, in a traditional interactive Scheme system, the top-level
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span> binding might be redefined, so the compiler cannot assume a
fixed <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span> binding (unless special flags or declarations
are used to compensate for the lack of a module system).</p><p>Even in the top-level environment, importing with <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._require%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">require</a></span>
enables some inlining optimizations. Although a <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span> definition
at the top level might shadow an imported <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span>, the shadowing
definition applies only to expressions evaluated later.</p><p>Within a module, inlining and constant-propagation optimizations take
additional advantage of the fact that definitions within a module
cannot be mutated when no <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span> is visible at compile
time. Such optimizations are unavailable in the top-level
environment. Although this optimization within modules is important
for performance, it hinders some forms of interactive development and
exploration. The <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=eval.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._compile-enforce-module-constants%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">compile-enforce-module-constants</a></span> parameter
disables the compiler&rsquo;s assumptions about module
definitions when interactive exploration is more important. See
<a href="module-set.html" data-pltdoc="x">Assignment and Redefinition</a> for more information.</p><p>The compiler may inline functions or propagate constants across module
boundaries. To avoid generating too much code in the case of function
inlining, the compiler is conservative when choosing candidates for
cross-module inlining; see <a href="performance.html#%28part._func-call-performance%29" data-pltdoc="x">Function-Call Optimizations</a> for
information on providing inlining hints to the compiler.</p><p>The later section <a href="performance.html#%28part._letrec-performance%29" data-pltdoc="x"><span class="RktSym"><span class="RktStxLink">letrec</span></span> Performance</a> provides some
additional caveats concerning inlining of module bindings.</p><h4 x-source-module="(lib &quot;scribblings/guide/guide.scrbl&quot;)" x-source-pkg="racket-doc" x-part-tag="&quot;func-call-performance&quot;">19.5<tt>&nbsp;</tt><a name="(part._func-call-performance)"></a>Function-Call Optimizations</h4><p>When the compiler detects a function call to an immediately visible
function, it generates more efficient code than for a generic call,
especially for tail calls. For example, given the program</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">letrec</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">odd</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">#f</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">even</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">sub1</a></span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">[</span><span class="RktSym">even</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="R
produce code that runs much faster via loop unrolling and related
optimizations.</p><p>Within a module form, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span>d variables are lexically scoped
like <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">letrec</a></span> bindings, and definitions within a module
therefore permit call optimizations, so</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">odd</span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktSym">....</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">even</span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktSym">....</span><span class="RktPn">)</span></td></tr></table></blockquote><p>within a module would perform the same as the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">letrec</a></span> version.</p><p>For direct calls to functions with keyword arguments, the compiler can
typically check keyword arguments statically and generate a direct
call to a non-keyword variant of the function, which reduces the
run-time overhead of keyword checking. This optimization applies only
for keyword-accepting procedures that are bound with <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span>.</p><p>For immediate calls to functions that are small enough, the compiler
may inline the function call by replacing the call with the body of
the function. In addition to the size of the target function&rsquo;s body,
the compiler&rsquo;s heuristics take into account the amount of inlining
already performed at the call site and whether the called function
itself calls functions other than simple primitive operations. When a
module is compiled, some functions defined at the module level are
determined to be candidates for inlining into other modules; normally,
only trivial functions are considered candidates for cross-module
inlining, but a programmer can wrap a function definition with
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=performance-hint.html%23%2528form._%2528%2528lib._racket%252Fperformance-hint..rkt%2529._begin-encourage-inline%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">begin-encourage-inline</a></span> to encourage inlining
of the function.</p><p>Primitive operations like <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._pair%7E3f%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">pair?</a></span>, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._car%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">car</a></span>, and
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._cdr%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">cdr</a></span> are inlined at the machine-code level by the bytecode or <a href="performance.html#%28tech._jit%29" class="techoutside" data-pltdoc="x"><span class="techinside">JIT</span></a>
compiler. See also the later section <a href="performance.html#%28part._fixnums%2Bflonums%29" data-pltdoc="x">Fixnum and Flonum Optimizations</a> for
information about inlined arithmetic operations.</p><h4 x-source-module="(lib &quot;scribblings/guide/guide.scrbl&quot;)" x-source-pkg="racket-doc" x-part-tag="&quot;Mutation_and_Performance&quot;">19.6<tt>&nbsp;</tt><a name="(part._.Mutation_and_.Performance)"></a>Mutation and Performance</h4><p>Using <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span> to mutate a variable can lead to bad
performance. For example, the microbenchmark</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><a href="Module_Syntax.html#%28part._hash-lang%29" class="RktModLink" data-pltdoc="x"><span class="RktMod">#lang</span></a><span class="hspace">&nbsp;</span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=index.html&amp;version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket/base</span></a></td></tr><tr><td><span class="hspace">&nbsp;</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">subtract-one</span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">sub1</a></span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=time.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fmore-scheme..rkt%2529._time%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">time</a></span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktSym">loop</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">n</span><span class="hspace">&nbsp;</span><span class="RktVal">4000000</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace">&nbsp;</span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
every iteration, leading to poor performance. A more clever compiler
could unravel the use of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span> in the first example, but since
mutation is discouraged (see <a href="set_.html#%28part._using-set%21%29" data-pltdoc="x">Guidelines for Using Assignment</a>), the compiler&rsquo;s
effort is spent elsewhere.</p><p>More significantly, mutation can obscure bindings where inlining and
constant-propagation might otherwise apply. For example, in</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">minus1</span><span class="hspace">&nbsp;</span><span class="RktVal">#f</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span><span class="hspace">&nbsp;</span><span class="RktSym">minus1</span><span class="hspace">&nbsp;</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">sub1</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktSym">loop</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">n</span><span class="hspace">&nbsp;</span><span class="RktVal">4000000</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace">&nbsp;</span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">'</span><span class="RktVal">done</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">loop</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">minus1</span><span class="hspace">&nbsp;</span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>the <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span> obscures the fact that <span class="RktSym">minus1</span> is just
another name for the built-in <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">sub1</a></span>.</p><h4 x-source-module="(lib &quot;scribblings/guide/guide.scrbl&quot;)" x-source-pkg="racket-doc" x-part-tag="&quot;letrec-performance&quot;">19.7<tt>&nbsp;</tt><a name="(part._letrec-performance)"></a><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">letrec</a></span> Performance</h4><p>When <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">letrec</a></span> is used to bind only procedures and literals,
then the compiler can treat the bindings in an optimal manner,
compiling uses of the bindings efficiently. When other kinds of
bindings are mixed with procedures, the compiler may be less able to
determine the control flow.</p><p>For example,</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">letrec</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">loop</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">'</span><span class="RktVal">done</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">loop</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">next</span><span class="hspace">&nbsp;</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">[</span><span class="RktSym">junk</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=Writing.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._display%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">display</a></span><span class="hspace">&nbsp;</span><span class="RktSym">loop</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">[</span><span class="RktSym">next</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/re
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=Writing.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._display%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">display</a></span> does not call <span class="RktSym">loop</span>. If it did, then
<span class="RktSym">loop</span> might refer to <span class="RktSym">next</span> before the binding is
available.</p><p>This caveat about <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">letrec</a></span> also applies to definitions of
functions and constants as internal definitions or in modules. A
definition sequence in a module body is analogous to a sequence of
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">letrec</a></span> bindings, and non-constant expressions in a module
body can interfere with the optimization of references to later
bindings.</p><h4 x-source-module="(lib &quot;scribblings/guide/guide.scrbl&quot;)" x-source-pkg="racket-doc" x-part-tag="&quot;fixnums+flonums&quot;">19.8<tt>&nbsp;</tt><a name="(part._fixnums+flonums)"></a>Fixnum and Flonum Optimizations</h4><p>A <a name="(tech._fixnum)"></a><span style="font-style: italic">fixnum</span> is a small exact integer. In this case, &ldquo;small&rdquo;
depends on the platform. For a 32-bit machine, numbers that can be
expressed in 29-30 bits plus a sign bit are represented as fixnums. On
a 64-bit machine, 60-62 bits plus a sign bit are available.</p><p>A <a name="(tech._flonum)"></a><span style="font-style: italic">flonum</span> is used to represent any inexact real number. They
correspond to 64-bit IEEE floating-point numbers on all platforms.</p><p>Inlined fixnum and flonum arithmetic operations are among the most
important advantages of the compiler. For example, when
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span> is applied to two arguments, the generated machine code
tests whether the two arguments are fixnums, and if so, it uses the
machine&rsquo;s instruction to add the numbers (and check for overflow). If
the two numbers are not fixnums, then it checks whether
both are flonums; in that case, the machine&rsquo;s floating-point
operations are used directly. For functions that take any number of
arguments, such as <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">+</a></span>, inlining works for two or more
arguments (except for <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._-%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x"><span class="nobreak">-</span></a></span>, whose one-argument case is also
inlined) when the arguments are either all fixnums or all flonums.</p><p>Flonums are typically <span style="font-style: italic">boxed</span>, which means that memory is
allocated to hold every result of a flonum computation. Fortunately,
the generational garbage collector (described later in
<a href="performance.html#%28part._gc-perf%29" data-pltdoc="x">Memory Management</a>) makes allocation for short-lived results
reasonably cheap. Fixnums, in contrast are never boxed, so they are
typically cheap to use.</p><blockquote class="refpara"><blockquote class="refcolumn"><blockquote class="refcontent"><p>See <a href="parallelism.html#%28part._effective-futures%29" data-pltdoc="x">Parallelism with Futures</a> for an example use of
<a href="performance.html#%28tech._flonum%29" class="techoutside" data-pltdoc="x"><span class="techinside">flonum</span></a>-specific operations.</p></blockquote></blockquote></blockquote><p>The <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=flonums.html&amp;version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket/flonum</span></a> library provides flonum-specific
operations, and combinations of flonum operations allow the compiler
to generate code that avoids boxing and unboxing intermediate
results. Besides results within immediate combinations,
flonum-specific results that are bound with <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span> and consumed
by a later flonum-specific operation are unboxed within temporary
storage. <span class="refelem"><span class="refcolumn"><span class="refcontent">Unboxing applies most reliably to uses of a
flonum-specific operation with two arguments.</span></span></span>
Finally, the compiler can detect some flonum-valued loop
accumulators and avoid boxing of the accumulator.
<span class="refelem"><span class="refcolumn"><span class="refcontent">Unboxing of local bindings and accumulators is not
supported by the <a href="performance.html#%28tech._bc%29" class="techoutside" data-pltdoc="x"><span class="techinside">BC</span></a> implementation&rsquo;s JIT for PowerPC.</span></span></span></p><p>For some loop patterns, the compiler may need hints to enable
unboxing. For example:</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">flvector-sum</span><span class="hspace">&nbsp;</span><span class="RktSym">vec</span><span class="hspace">&nbsp;</span><span class="RktSym">init</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktSym">loop</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">i</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">]</span><span class="hspace">&nbsp;</span><span class="RktPn">[</span><span class="RktSym">sum</span><span class="hspace">&nbsp;</span><span class="RktSym">init</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">fx=</span><span class="hspace">&nbsp;</span><span class="RktSym">i</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._flvector-length%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">flvector-length</a></span><span class="hspace">&nbsp;</span><span class="RktSym">vec</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktSym">sum</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">loop</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">fx+</span><span class="hspace">&nbsp;</span><span class="RktSym">i</span><span class="hspace">&nbsp;</span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._fl%252B%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">fl+</a></span><span class="hspace">&nbsp;</span><span class="RktSym">sum</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._flvector-ref%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">flvector-ref</a></span><span class="hspace">&nbsp;</span><span class="RktSym">vec</span><span class="hspace">&nbsp;</span><span class="RktSym">i</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span
two reasons: it cannot determine locally that its initial value from
<span class="RktSym">init</span> will be a flonum, and it cannot tell locally that the
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=Equality.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._eq%7E3f%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">eq?</a></span> identity of the result <span class="RktSym">sum</span> is irrelevant.
Changing the reference <span class="RktSym">init</span> to <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._fl%252B%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">fl+</a></span><span class="stt"> </span><span class="RktSym">init</span><span class="RktPn">)</span> and
changing the result <span class="RktSym">sum</span> to <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._fl%252B%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">fl+</a></span><span class="stt"> </span><span class="RktSym">sum</span><span class="RktPn">)</span> gives the
compiler hints and license to unbox <span class="RktSym">sum</span>.</p><p>The bytecode decompiler (see <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=raco&amp;rel=decompile.html&amp;version=8.6" class="Sq" data-pltdoc="x"><span class="stt">raco decompile</span>: Decompiling Bytecode</a>) for the <a href="performance.html#%28tech._bc%29" class="techoutside" data-pltdoc="x"><span class="techinside">BC</span></a> implementation
annotates combinations where the JIT can avoid boxes with
<span class="RktSym">#%flonum</span>, <span class="RktSym">#%as-flonum</span>, and
<span class="RktSym">#%from-flonum</span>. For the <a href="performance.html#%28tech._c%29" class="techoutside" data-pltdoc="x"><span class="techinside">CS</span></a> variant, the
&ldquo;bytecode&rdquo; decompiler shows machine code, but install the
<span class="stt">"disassemble"</span> package to potentially see the machine code as
machine-specific assembly code. See also <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=compiler.html%23%2528part._compiler-inspect%2529&amp;version=8.6" class="Sq" data-pltdoc="x">Inspecting Compiler Passes</a>.</p><p>The <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=unsafe.html&amp;version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket/unsafe/ops</span></a> library provides unchecked
fixnum- and flonum-specific operations. Unchecked flonum-specific
operations allow unboxing, and sometimes they allow the compiler to
reorder expressions to improve performance. See also
<a href="performance.html#%28part._unchecked-unsafe%29" data-pltdoc="x">Unchecked, Unsafe Operations</a>, especially the warnings about unsafety.</p><h4 x-source-module="(lib &quot;scribblings/guide/guide.scrbl&quot;)" x-source-pkg="racket-doc" x-part-tag="&quot;unchecked-unsafe&quot;">19.9<tt>&nbsp;</tt><a name="(part._unchecked-unsafe)"></a>Unchecked, Unsafe Operations</h4><p>The <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=unsafe.html&amp;version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket/unsafe/ops</span></a> library provides functions that
are like other functions in <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=index.html&amp;version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket/base</span></a>, but they
assume (instead of checking) that provided arguments are of the right
type. For example, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=unsafe.html%23%2528def._%2528%2528lib._racket%252Funsafe%252Fops..rkt%2529._unsafe-vector-ref%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">unsafe-vector-ref</a></span> accesses an element from
a vector without checking that its first argument is actually a vector
and without checking that the given index is in bounds. For tight
loops that use these functions, avoiding checks can sometimes speed
the computation, though the benefits vary for different unchecked
functions and different contexts.</p><p>Beware that, as &ldquo;unsafe&rdquo; in the library and function names suggest,
misusing the exports of <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=unsafe.html&amp;version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket/unsafe/ops</span></a> can lead to
crashes or memory corruption.</p><h4 x-source-module="(lib &quot;scribblings/guide/guide.scrbl&quot;)" x-source-pkg="racket-doc" x-part-tag="&quot;ffi-pointer-access&quot;">19.10<tt>&nbsp;</tt><a name="(part._ffi-pointer-access)"></a>Foreign Pointers</h4><p>The <a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=index.html&amp;version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">ffi/unsafe</span></a> library provides functions for unsafely
reading and writing arbitrary pointer values. The compiler recognizes uses
of <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=foreign_pointer-funcs.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529._ptr-ref%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">ptr-ref</a></span> and <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=foreign_pointer-funcs.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529._ptr-set%2521%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">ptr-set!</a></span> where the second argument is
a direct reference to one of the following built-in C types:
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__int8%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">_int8</a></span>, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__int16%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">_int16</a></span>, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__int32%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">_int32</a></span>, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__int64%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">_int64</a></span>,
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__double%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">_double</a></span>, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__float%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">_float</a></span>, and <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=Pointer_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__pointer%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">_pointer</a></span>. Then, if the
first argument to <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=foreign_pointer-funcs.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529._ptr-ref%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">ptr-ref</a></span> or <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=foreign_pointer-funcs.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529._ptr-set%2521%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">ptr-set!</a></span> is a C pointer
(not a byte string), then the pointer read or write is performed
inline in the generated code.</p><p>The bytecode compiler will optimize references to integer
abbreviations like <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=Numeric_Types.html%23%2528def._%2528%2528lib._ffi%252Funsafe..rkt%2529.__int%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">_int</a></span> to C types like
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__int32%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">_int32</a></span>&#8212;<wbr></wbr>where the representation sizes are constant across
platforms&#8212;<wbr></wbr>so the compiler can specialize access with those C types. C
types such as <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=Numeric_Types.html%23%2528def._%2528%2528lib._ffi%252Funsafe..rkt%2529.__long%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">_long</a></span> or <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=Numeric_Types.html%23%2528def._%2528%2528lib._ffi%252Funsafe..rkt%2529.__intptr%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">_intptr</a></span> are not constant
across platforms, so their uses are not as consistently specialized.</p><p>Pointer reads and writes using <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__float%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">_float</a></span> or <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=foreign&amp;rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__double%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">_double</a></span> are
not currently subject to unboxing optimizations.</p><h4 x-source-module="(lib &quot;scribblings/guide/guide.scrbl&quot;)" x-source-pkg="racket-doc" x-part-tag="&quot;regexp-perf&quot;">19.11<tt>&nbsp;</tt><a name="(part._regexp-perf)"></a>Regular Expression Performance</h4><p>When a string or byte string is provided to a function like
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._regexp-match%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">regexp-match</a></span>, then the string is internally compiled into
a <a href="regexp.html#%28tech._regexp%29" class="techoutside" data-pltdoc="x"><span class="techinside">regexp</span></a> value. Instead of supplying a string or byte string
multiple times as a pattern for matching, compile the pattern once to
a <a href="regexp.html#%28tech._regexp%29" class="techoutside" data-pltdoc="x"><span class="techinside">regexp</span></a> value using <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._regexp%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">regexp</a></span>, <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._byte-regexp%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">byte-regexp</a></span>,
<span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._pregexp%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">pregexp</a></span>, or <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._byte-pregexp%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">byte-pregexp</a></span>. In place of a constant
string or byte string, write a constant <a href="regexp.html#%28tech._regexp%29" class="techoutside" data-pltdoc="x"><span class="techinside">regexp</span></a> using an
<span class="RktInBG"><span class="hspace"></span><span class="RktIn">#rx</span><span class="hspace"></span></span> or <span class="RktInBG"><span class="hspace"></span><span class="RktIn">#px</span><span class="hspace"></span></span> prefix.</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">slow-matcher</span><span class="hspace">&nbsp;</span><span class="RktSym">str</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._regexp-match%7E3f%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">regexp-match?</a></span><span class="hspace">&nbsp;</span><span class="RktVal">"[0-9]+"</span><span class="hspace">&nbsp;</span><span class="RktSym">str</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">fast-matcher</span><span class="hspace">&nbsp;</span><span class="RktSym">str</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._regexp-match%7E3f%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">regexp-match?</a></span><span class="hspace">&nbsp;</span><span class="RktVal">#rx"[0-9]+"</span><span class="hspace">&nbsp;</span><span class="RktSym">str</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">make-slow-matcher</span><span class="hspace">&nbsp;</span><span class="RktSym">pattern-str</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">str</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._regexp-match%7E3f%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">regexp-match?</a
<a href="performance.html#%28part._virtual-machines%29" data-pltdoc="x">virtual machines</a> each use a modern,
<a name="(tech._generational._garbage._collector)"></a><span style="font-style: italic">generational garbage collector</span> that makes allocation
relatively cheap for short-lived objects. The <a href="performance.html#%28tech._cgc%29" class="techoutside" data-pltdoc="x"><span class="techinside">CGC</span></a> variant of <a href="performance.html#%28tech._bc%29" class="techoutside" data-pltdoc="x"><span class="techinside">BC</span></a> uses
a <a name="(tech._conservative._garbage._collector)"></a><span style="font-style: italic">conservative garbage collector</span> which facilitates
interaction with C code at the expense of both precision and speed for
Racket memory management.</p><p>Although memory allocation is reasonably cheap, avoiding allocation
altogether is often faster. One particular place where allocation
can be avoided sometimes is in <a name="(tech._closure)"></a><span style="font-style: italic">closures</span>, which are the
run-time representation of functions that contain free variables.
For example,</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktSym">loop</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">n</span><span class="hspace">&nbsp;</span><span class="RktVal">40000000</span><span class="RktPn">]</span><span class="hspace">&nbsp;</span><span class="RktPn">[</span><span class="RktSym">prev-thunk</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktVal">#f</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace">&nbsp;</span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">prev-thunk</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">loop</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">sub1</a></span><span class="hspace">&nbsp;</span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>allocates a closure on every iteration, since <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="stt">
effectively saves <span class="RktSym">n</span>.</p><p>The compiler can eliminate many closures automatically. For example,
in</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktSym">loop</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">n</span><span class="hspace">&nbsp;</span><span class="RktVal">40000000</span><span class="RktPn">]</span><span class="hspace">&nbsp;</span><span class="RktPn">[</span><span class="RktSym">prev-val</span><span class="hspace">&nbsp;</span><span class="RktVal">#f</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">prev-thunk</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace">&nbsp;</span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktSym">prev-val</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">loop</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">sub1</a></span><span class="hspace">&nbsp;</span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">prev-thunk</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr></table></blockquote><p>no closure is ever allocated for <span class="RktSym">prev-thunk</span>, because its only
application is visible, and so it is inlined. Similarly, in</p><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktSym">n-loop</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">n</span><span class="hspace">&nbsp;</span><span class="RktVal">400000</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace">&nbsp;</span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktVal">'</span><span class="RktVal">done</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace">&nbsp;</span><span class="RktSym">m-loop</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">m</span><span class="hspace">&nbsp;</span><span class="RktVal">100</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace">&nbsp;</span><span class="RktSym">m</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">n-loop</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">sub1</a></span><span class="hspace">&nbsp;</span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">m-
<span class="RktSym">m-loop</span> involves a closure over <span class="RktSym">n</span>, but the compiler
automatically converts the closure to pass itself <span class="RktSym">n</span> as an
argument instead.</p><h4 x-source-module="(lib &quot;scribblings/guide/guide.scrbl&quot;)" x-source-pkg="racket-doc" x-part-tag="&quot;Reachability and Garbage Collection&quot;">19.13<tt>&nbsp;</tt><a name="(part._.Reachability._and._.Garbage._.Collection)"></a>Reachability and Garbage Collection</h4><p>In general, Racket re-uses the storage for a value when the garbage
collector can prove that the object is unreachable from any other
(reachable) value. Reachability is a low-level, abstraction-breaking
concept, and thus it requires detailed knowledge of the runtime system
to predict exactly when values are reachable from each other. But
generally one value is reachable from a second one when there is some
operation to recover the original value from the second one.</p><p>To help programmers understand when an object is no longer reachable and its
storage can be reused,
Racket provides <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._make-weak-box%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">make-weak-box</a></span> and <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._weak-box-value%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">weak-box-value</a></span>,
the creator and accessor for a one-record struct that the garbage
collector treats specially. An object inside a weak box does not count
as reachable, and so <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._weak-box-value%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">weak-box-value</a></span> might return the object
inside the box, but it might also return <span class="RktVal">#f</span> to indicate
that the object was otherwise unreachable and garbage collected.
Note that unless a garbage collection actually occurs, the value will
remain inside the weak box, even if it is unreachable.</p><p><div class="SIntrapara">For example, consider this program:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><a href="Module_Syntax.html#%28part._hash-lang%29" class="RktModLink" data-pltdoc="x"><span class="RktMod">#lang</span></a><span class="hspace">&nbsp;</span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=index.html&amp;version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket</span></a></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define-struct.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._struct%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">struct</a></span><span class="hspace">&nbsp;</span><span class="RktSym">fish</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">weight</span><span class="hspace">&nbsp;</span><span class="RktSym">color</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">#:transparent</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">f</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">fish</span><span class="hspace">&nbsp;</span><span class="RktVal">7</span><span class="hspace">&nbsp;</span><span class="RktVal">'</span><span class="RktVal">blue</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">b</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._make-weak-box%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">make-weak-box</a></span><span class="hspace">&nbsp;</span><span class="RktSym">f</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=Writing.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._printf%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">printf</a></span><span class="hspace">&nbsp;</span><span class="RktVal">"b has ~s\n"</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._weak-box-value%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">weak-box-value</a></span><span class="hspace">&nbsp;</span><span class="RktSym">b</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">collect-garbage</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn"
definition of <span class="RktSym">f</span> still holds onto the fish. If the program
were this, however:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><a href="Module_Syntax.html#%28part._hash-lang%29" class="RktModLink" data-pltdoc="x"><span class="RktMod">#lang</span></a><span class="hspace">&nbsp;</span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=index.html&amp;version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket</span></a></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define-struct.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._struct%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">struct</a></span><span class="hspace">&nbsp;</span><span class="RktSym">fish</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">weight</span><span class="hspace">&nbsp;</span><span class="RktSym">color</span><span class="RktPn">)</span><span class="hspace">&nbsp;</span><span class="RktPn">#:transparent</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">f</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">fish</span><span class="hspace">&nbsp;</span><span class="RktVal">7</span><span class="hspace">&nbsp;</span><span class="RktVal">'</span><span class="RktVal">blue</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace">&nbsp;</span><span class="RktSym">b</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._make-weak-box%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">make-weak-box</a></span><span class="hspace">&nbsp;</span><span class="RktSym">f</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=Writing.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._printf%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">printf</a></span><span class="hspace">&nbsp;</span><span class="RktVal">"b has ~s\n"</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._weak-box-value%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">weak-box-value</a></span><span class="hspace">&nbsp;</span><span class="RktSym">b</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span><span class="hspace">&nbsp;</span><span class="RktSym">f</span><span class="hspace">&nbsp;</spa
no reference to the fish exists (other than the one in the box).</div></p><p><div class="SIntrapara">As a first approximation, all values in Racket must be allocated and will
demonstrate behavior similar to the fish above.
There are a number of exceptions, however:
</div><div class="SIntrapara"><ul><li><p>Small integers (recognizable with <span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._fixnum%7E3f%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">fixnum?</a></span>) are
always available without explicit
allocation. From the perspective of the garbage collector
and weak boxes, their storage is never reclaimed. (Due to
clever representation techniques, however, their storage
does not count towards the space that Racket uses.
That is, they are effectively free.)</p></li><li><p>Procedures where
the compiler can see all of their call sites may never be
allocated at all (as discussed above).
Similar optimizations may also eliminate
the allocation for other kinds of values.</p></li><li><p>Interned symbols are allocated only once (per place). A table inside
Racket tracks this allocation so a symbol may not become garbage
because that table holds onto it.</p></li><li><p>Reachability is only approximate with the <a href="performance.html#%28tech._cgc%29" class="techoutside" data-pltdoc="x"><span class="techinside">CGC</span></a> collector (i.e.,
a value may appear reachable to that collector when there is,
in fact, no way to reach it anymore).</p></li></ul></div></p><h4 x-source-module="(lib &quot;scribblings/guide/guide.scrbl&quot;)" x-source-pkg="racket-doc" x-part-tag="&quot;Weak_Boxes_and_Testing&quot;">19.14<tt>&nbsp;</tt><a name="(part._.Weak_.Boxes_and_.Testing)"></a>Weak Boxes and Testing</h4><p>One important use of weak boxes is in testing that some abstraction properly
releases storage for data it no longer needs, but there is a gotcha that
can easily cause such test cases to pass improperly.</p><p>Imagine you&rsquo;re designing a data structure that needs to
hold onto some value temporarily but then should clear a field or
somehow break a link to avoid referencing that value so it can be
collected. Weak boxes are a good way to test that your data structure
properly clears the value. That is, you might write a test case
that builds a value, extracts some other value from it
(that you hope becomes unreachable), puts the extracted value into a weak-box,
and then checks to see if the value disappears from the box.</p><p><div class="SIntrapara">This code is one attempt to follow that pattern, but it has a subtle bug:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><a href="Module_Syntax.html#%28part._hash-lang%29" class="RktModLink" data-pltdoc="x"><span class="RktMod">#lang</span></a><span class="hspace">&nbsp;</span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=index.html&amp;version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket</span></a></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%252A%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">let*</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">fishes</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">list</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">fish</span><span class="hspace">&nbsp;</span><span class="RktVal">8</span><span class="hspace">&nbsp;</span><span class="RktVal">'</span><span class="RktVal">red</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">fish</span><span class="hspace">&nbsp;</span><span class="RktVal">7</span><span class="hspace">&nbsp;</span><span class="RktVal">'</span><span class="RktVal">blue</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">[</span><span class="RktSym">wb</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._make-weak-box%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">make-weak-box</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list-ref%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">list-ref</a></span><span class="hspace">&nbsp;</span><span class="RktSym">fishes</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">collect-garbage</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=Writing.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._printf%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">printf</a></span><span class="hspace">&nbsp;</span><span class="RktVal">"still there? ~s\n"</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="R
because <span class="RktVar">fishes</span> no longer holds onto the value, but
because <span class="RktVar">fishes</span> itself is not reachable anymore!</div></p><p><div class="SIntrapara">Change the program to this one:
</div><div class="SIntrapara"><blockquote class="SCodeFlow"><table cellspacing="0" cellpadding="0" class="RktBlk"><tr><td><a href="Module_Syntax.html#%28part._hash-lang%29" class="RktModLink" data-pltdoc="x"><span class="RktMod">#lang</span></a><span class="hspace">&nbsp;</span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=index.html&amp;version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket</span></a></td></tr><tr><td><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%252A%2529%2529&amp;version=8.6" class="RktStxLink Sq" data-pltdoc="x">let*</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">fishes</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">list</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym">fish</span><span class="hspace">&nbsp;</span><span class="RktVal">8</span><span class="hspace">&nbsp;</span><span class="RktVal">'</span><span class="RktVal">red</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym">fish</span><span class="hspace">&nbsp;</span><span class="RktVal">7</span><span class="hspace">&nbsp;</span><span class="RktVal">'</span><span class="RktVal">blue</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="RktPn">[</span><span class="RktSym">wb</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._make-weak-box%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">make-weak-box</a></span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list-ref%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">list-ref</a></span><span class="hspace">&nbsp;</span><span class="RktSym">fishes</span><span class="hspace">&nbsp;</span><span class="RktVal">0</span><span class="RktPn">)</span><span class="RktPn">)</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">collect-garbage</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">&nbsp;&nbsp;</span><span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=Writing.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._printf%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">printf</a></span><span class="hspace">&nbsp;</span><span class="RktVal">"still there? ~s\n"</span><span class="hspace">&nbsp;</span><span class="RktPn">(</span><span class="R
occurrence of the variable <span class="RktVar">fishes</span>. That constitutes
a reference to the list, ensuring that the list is not itself
garbage collected, and thus the red fish is not either.</div></p><h4 x-source-module="(lib &quot;scribblings/guide/guide.scrbl&quot;)" x-source-pkg="racket-doc" x-part-tag="&quot;Reducing_Garbage_Collection_Pauses&quot;">19.15<tt>&nbsp;</tt><a name="(part._.Reducing_.Garbage_.Collection_.Pauses)"></a>Reducing Garbage Collection Pauses</h4><p>By default, Racket&rsquo;s <a href="performance.html#%28tech._generational._garbage._collector%29" class="techoutside" data-pltdoc="x"><span class="techinside">generational garbage collector</span></a> creates
brief pauses for frequent <a name="(tech._minor._collection)"></a><span style="font-style: italic">minor collections</span>, which inspect
only the most recently allocated objects, and long pauses for infrequent
<a name="(tech._major._collection)"></a><span style="font-style: italic">major collections</span>, which re-inspect all memory.</p><p>For some applications, such as animations and games,
long pauses due to a major collection can interfere
unacceptably with a program&rsquo;s operation. To reduce major-collection
pauses, the <a href="performance.html#%28tech._3m%29" class="techoutside" data-pltdoc="x"><span class="techinside">3m</span></a> garbage collector supports <a name="(tech._incremental._garbage._collection)"></a><span style="font-style: italic">incremental
garbage-collection</span> mode, and the <a href="performance.html#%28tech._c%29" class="techoutside" data-pltdoc="x"><span class="techinside">CS</span></a> garbage collector supports
a useful approximation:</p><ul><li><p>In <a href="performance.html#%28tech._3m%29" class="techoutside" data-pltdoc="x"><span class="techinside">3m</span></a>&rsquo;s incremental mode, minor collections create longer
(but still relatively short) pauses by performing extra work
toward the next major collection. If all goes well, most of a
major collection&rsquo;s work has been performed by minor collections
the time that a major collection is needed, so the major
collection&rsquo;s pause is as short as a minor collection&rsquo;s pause.
Incremental mode tends to run more slowly overall, but it can
provide much more consistent real-time behavior.</p></li><li><p>In <a href="performance.html#%28tech._c%29" class="techoutside" data-pltdoc="x"><span class="techinside">CS</span></a>&rsquo;s incremental mode, objects are never promoted out
of the category of &ldquo;recently allocated,&rdquo; although there are
degrees of &ldquo;recently&rdquo; so that most minor collections can still
skip recent-but-not-too-recent objects. In the common case that
most of the memory use for animation or game is allocated on
startup (including its code and the code of the Racket runtime
system), a major collection may never become necessary.</p></li></ul><p>If the <span class="stt">PLT_INCREMENTAL_GC</span> environment variable is set to a
value that starts with <span class="RktInBG"><span class="hspace"></span><span class="RktIn">0</span><span class="hspace"></span></span>, <span class="RktInBG"><span class="hspace"></span><span class="RktIn">n</span><span class="hspace"></span></span>, or <span class="RktInBG"><span class="hspace"></span><span class="RktIn">N</span><span class="hspace"></span></span> when
Racket starts, incremental mode is permanently disabled. For
<a href="performance.html#%28tech._3m%29" class="techoutside" data-pltdoc="x"><span class="techinside">3m</span></a>, if the <span class="stt">PLT_INCREMENTAL_GC</span> environment variable is
set to a value that starts with <span class="RktInBG"><span class="hspace"></span><span class="RktIn">1</span><span class="hspace"></span></span>, <span class="RktInBG"><span class="hspace"></span><span class="RktIn">y</span><span class="hspace"></span></span>, or
<span class="RktInBG"><span class="hspace"></span><span class="RktIn">Y</span><span class="hspace"></span></span> when Racket starts, incremental mode is permanently
enabled. Since incremental mode is only useful for certain parts of
some programs, however, and since the need for incremental mode is a
property of a program rather than its environment, the preferred way
to enable incremental mode is with <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">collect-garbage</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">incremental</span><span class="RktPn">)</span>.</p><p>Calling <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">collect-garbage</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">incremental</span><span class="RktPn">)</span> does not perform an
immediate garbage collection, but instead requests that each minor
collection perform incremental work up to the next major collection
(unless incremental model is permanently disabled). The request
expires with the next major collection. Make a call to
<span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">collect-garbage</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">incremental</span><span class="RktPn">)</span> in any repeating task within
an application that needs to be responsive in real time. Force a full
collection with <span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">collect-garbage</a></span><span class="RktPn">)</span> just before an initial
<span class="RktPn">(</span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&amp;rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&amp;version=8.6" class="RktValLink Sq" data-pltdoc="x">collect-garbage</a></span><span class="stt"> </span><span class="RktVal">'</span><span class="RktVal">incremental</span><span class="RktPn">)</span> to initiate incremental mode
from an optimal state.</p><p>To check whether incremental mode is in use and how it affects pause
times, enable <span class="stt">debug</span>-level logging output for the
<span class="RktSym">GC</span> topic. For example,</p><p><span class="hspace">&nbsp;&nbsp;</span><span class="stt">racket -W "debug@GC error" main.rkt</span></p><p>runs <span class="stt">"main.rkt"</span> with garbage-collection logging to stderr
(while preserving <span class="stt">error</span>-level logging for all topics). Minor
collections are reported by <span class="RktInBG"><span class="hspace"></span><span class="RktIn">min</span><span class="hspace"></span></span> lines, increment-mode minor
collections on <a href="performance.html#%28tech._3m%29" class="techoutside" data-pltdoc="x"><span class="techinside">3m</span></a> are reported with <span class="RktInBG"><span class="hspace"></span><span class="RktIn">mIn</span><span class="hspace"></span></span> lines, and major
collections are reported with <span class="RktInBG"><span class="hspace"></span><span class="RktIn">MAJ</span><span class="hspace"></span></span> lines.</p><div class="navsetbottom"><span class="navleft"><form class="searchform"><input class="searchbox" id="searchbox" type="text" tabindex="1" placeholder="...search manuals..." title="Enter a search string to search the manuals" onkeypress="return DoSearchKey(event, this, &quot;8.6&quot;, &quot;../&quot;);"/></form>&nbsp;&nbsp;<a href="https://docs.racket-lang.org/index.html" title="up to the documentation top" data-pltdoc="x" onclick="return GotoPLTRoot(&quot;8.6&quot;);">top</a><span class="tocsettoggle">&nbsp;&nbsp;<a href="javascript:void(0);" title="show/hide table of contents" onclick="TocsetToggle();">contents</a></span></span><span class="navright">&nbsp;&nbsp;<a href="concurrency.html" title="backward to &quot;18 Concurrency and Synchronization&quot;" data-pltdoc="x">&larr; prev</a>&nbsp;&nbsp;<a href="index.html" title="up to &quot;The Racket Guide&quot;" data-pltdoc="x">up</a>&nbsp;&nbsp;<a href="parallelism.html" title="forward to &quot;20 Parallelism&quot;" data-pltdoc="x">next &rarr;</a></span>&nbsp;</div></div></div><div id="contextindicator">&nbsp;</div></body></html>