348 lines
149 KiB
HTML
348 lines
149 KiB
HTML
|
<!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 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,"tocview_0");">▼</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 </td><td><a href="intro.html" class="tocviewlink" data-pltdoc="x">Welcome to Racket</a></td></tr><tr><td align="right">2 </td><td><a href="to-scheme.html" class="tocviewlink" data-pltdoc="x">Racket Essentials</a></td></tr><tr><td align="right">3 </td><td><a href="datatypes.html" class="tocviewlink" data-pltdoc="x">Built-<wbr></wbr>In Datatypes</a></td></tr><tr><td align="right">4 </td><td><a href="scheme-forms.html" class="tocviewlink" data-pltdoc="x">Expressions and Definitions</a></td></tr><tr><td align="right">5 </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 </td><td><a href="modules.html" class="tocviewlink" data-pltdoc="x">Modules</a></td></tr><tr><td align="right">7 </td><td><a href="contracts.html" class="tocviewlink" data-pltdoc="x">Contracts</a></td></tr><tr><td align="right">8 </td><td><a href="i_o.html" class="tocviewlink" data-pltdoc="x">Input and Output</a></td></tr><tr><td align="right">9 </td><td><a href="regexp.html" class="tocviewlink" data-pltdoc="x">Regular Expressions</a></td></tr><tr><td align="right">10 </td><td><a href="control.html" class="tocviewlink" data-pltdoc="x">Exceptions and Control</a></td></tr><tr><td align="right">11 </td><td><a href="for.html" class="tocviewlink" data-pltdoc="x">Iterations and Comprehensions</a></td></tr><tr><td align="right">12 </td><td><a href="match.html" class="tocviewlink" data-pltdoc="x">Pattern Matching</a></td></tr><tr><td align="right">13 </td><td><a href="classes.html" class="tocviewlink" data-pltdoc="x">Classes and Objects</a></td></tr><tr><td align="right">14 </td><td><a href="units.html" class="tocviewlink" data-pltdoc="x">Units</a></td></tr><tr><td align="right">15 </td><td><a href="reflection.html" class="tocviewlink" data-pltdoc="x">Reflection and Dynamic Evaluation</a></td></tr><tr><td align="right">16 </td><td><a href="macros.html" class="tocviewlink" data-pltdoc="x">Macros</a></td></tr><tr><td align="right">17 </td><td><a href="languages.html" class="tocviewlink" data-pltdoc="x">Creating Languages</a></td></tr><tr><td align="right">18 </td><td><a href="concurrency.html" class="tocviewlink" data-
|
||
|
everything and the cost of nothing.” 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&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&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—<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 "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""DrRacket-perf"">19.1<tt> </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&rel=index.html&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’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 "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""virtual-machines"">19.2<tt> </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&rel=runtime.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._system-type%2529%2529&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&rel=runtime.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._system-type%2529%2529&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&rel=runtime.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._system-type%2529%2529&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&rel=runtime.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._system-type%2529%2529&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’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 “conservative”
|
||
|
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&rel=overview.html%23%2528part._.C.G.C._versus._3m%2529&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&rel=index.html&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&rel=runtime.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._system-type%2529%2529&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&rel=index.html&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 "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""JIT"">19.3<tt> </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 “bytecode” 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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&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&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&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&rel=eval.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._current-compile-target-machine%2529%2529&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’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&rel=eval.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._eval-jit-enabled%2529%2529&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&rel=eval.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._eval-jit-enabled%2529%2529&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&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&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>’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&rel=compiler.html%23%2528part._compiler-inspect%2529&version=8.6" class="Sq" data-pltdoc="x">Inspecting Compiler Passes</a>.</p><h4 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""modules-performance"">19.4<tt> </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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&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&rel=index.html&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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&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&rel=require.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._require%2529%2529&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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&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&rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&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&rel=eval.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._compile-enforce-module-constants%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">compile-enforce-module-constants</a></span> parameter
|
||
|
disables the compiler’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 "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""func-call-performance"">19.5<tt> </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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">letrec</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">odd</span><span class="hspace"> </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&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace"> </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&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">#f</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">even</span><span class="hspace"> </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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">sub1</a></span><span class="hspace"> </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"> </span><span class="RktPn">[</span><span class="RktSym">even</span><span class="hspace"> </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&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace"> </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&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&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&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">odd</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </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&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">even</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&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&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&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’s body,
|
||
|
the compiler’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&rel=performance-hint.html%23%2528form._%2528%2528lib._racket%252Fperformance-hint..rkt%2529._begin-encourage-inline%2529%2529&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&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._pair%7E3f%2529%2529&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&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._car%2529%2529&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&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._cdr%2529%2529&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 "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""Mutation_and_Performance"">19.6<tt> </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&rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&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"> </span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=index.html&version=8.6" class="RktModLink Sq" data-pltdoc="x"><span class="RktSym">racket/base</span></a></td></tr><tr><td><span class="hspace"> </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&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">subtract-one</span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="hspace"> </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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=time.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fmore-scheme..rkt%2529._time%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">time</a></span></td></tr><tr><td><span class="hspace"> </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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">4000000</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace"> </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&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace">
|
||
|
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&rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&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’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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">minus1</span><span class="hspace"> </span><span class="RktVal">#f</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span><span class="hspace"> </span><span class="RktSym">minus1</span><span class="hspace"> </span><span class="RktSym"><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">sub1</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">4000000</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace"> </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&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">done</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">minus1</span><span class="hspace"> </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&rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">sub1</a></span>.</p><h4 x-source-module="(lib "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""letrec-performance"">19.7<tt> </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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">letrec</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">loop</span><span class="hspace"> </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&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace"> </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&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">x</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">done</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">next</span><span class="hspace"> </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"> </span><span class="RktPn">[</span><span class="RktSym">junk</span><span class="hspace"> </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&rel=Writing.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._display%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">display</a></span><span class="hspace"> </span><span class="RktSym">loop</span><span class="RktPn">)</span><span class="RktPn">]</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">next</span><span class="hspace"> </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&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">x</span><span class="RktPn">)</span><span class="hspace"> </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&rel=Writing.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._display%2529%2529&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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._letrec%2529%2529&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 "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""fixnums+flonums"">19.8<tt> </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, “small”
|
||
|
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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&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’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’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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._%252B%2529%2529&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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._-%2529%2529&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&rel=flonums.html&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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&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’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&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">flvector-sum</span><span class="hspace"> </span><span class="RktSym">vec</span><span class="hspace"> </span><span class="RktSym">init</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">i</span><span class="hspace"> </span><span class="RktVal">0</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">sum</span><span class="hspace"> </span><span class="RktSym">init</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fx=</span><span class="hspace"> </span><span class="RktSym">i</span><span class="hspace"> </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&rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._flvector-length%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">flvector-length</a></span><span class="hspace"> </span><span class="RktSym">vec</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">sum</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fx+</span><span class="hspace"> </span><span class="RktSym">i</span><span class="hspace"> </span><span class="RktVal">1</span><span class="RktPn">)</span><span class="hspace"> </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&rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._fl%252B%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">fl+</a></span><span class="hspace"> </span><span class="RktSym">sum</span><span class="hspace"> </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&rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._flvector-ref%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">flvector-ref</a></span><span class="hspace"> </span><span class="RktSym">vec</span><span class="hspace"> </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&rel=Equality.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._eq%7E3f%2529%2529&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&rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._fl%252B%2529%2529&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&rel=flonums.html%23%2528def._%2528%2528lib._racket%252Fflonum..rkt%2529._fl%252B%2529%2529&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&rel=decompile.html&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
|
||
|
“bytecode” 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&rel=compiler.html%23%2528part._compiler-inspect%2529&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&rel=unsafe.html&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 "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""unchecked-unsafe"">19.9<tt> </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&rel=unsafe.html&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&rel=index.html&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&rel=unsafe.html%23%2528def._%2528%2528lib._racket%252Funsafe%252Fops..rkt%2529._unsafe-vector-ref%2529%2529&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 “unsafe” 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&rel=unsafe.html&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 "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""ffi-pointer-access"">19.10<tt> </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&rel=index.html&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&rel=foreign_pointer-funcs.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529._ptr-ref%2529%2529&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&rel=foreign_pointer-funcs.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529._ptr-set%2521%2529%2529&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&rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__int8%2529%2529&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&rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__int16%2529%2529&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&rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__int32%2529%2529&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&rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__int64%2529%2529&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&rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__double%2529%2529&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&rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__float%2529%2529&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&rel=Pointer_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__pointer%2529%2529&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&rel=foreign_pointer-funcs.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529._ptr-ref%2529%2529&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&rel=foreign_pointer-funcs.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529._ptr-set%2521%2529%2529&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&rel=Numeric_Types.html%23%2528def._%2528%2528lib._ffi%252Funsafe..rkt%2529.__int%2529%2529&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&rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__int32%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">_int32</a></span>—<wbr></wbr>where the representation sizes are constant across
|
||
|
platforms—<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&rel=Numeric_Types.html%23%2528def._%2528%2528lib._ffi%252Funsafe..rkt%2529.__long%2529%2529&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&rel=Numeric_Types.html%23%2528def._%2528%2528lib._ffi%252Funsafe..rkt%2529.__intptr%2529%2529&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&rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__float%2529%2529&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&rel=Numeric_Types.html%23%2528def._%2528%2528quote._%7E23%7E25foreign%2529.__double%2529%2529&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 "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""regexp-perf"">19.11<tt> </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&rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._regexp-match%2529%2529&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&rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._regexp%2529%2529&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&rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._byte-regexp%2529%2529&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&rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._pregexp%2529%2529&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&rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._byte-pregexp%2529%2529&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&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">slow-matcher</span><span class="hspace"> </span><span class="RktSym">str</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._regexp-match%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">regexp-match?</a></span><span class="hspace"> </span><span class="RktVal">"[0-9]+"</span><span class="hspace"> </span><span class="RktSym">str</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fast-matcher</span><span class="hspace"> </span><span class="RktSym">str</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._regexp-match%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">regexp-match?</a></span><span class="hspace"> </span><span class="RktVal">#rx"[0-9]+"</span><span class="hspace"> </span><span class="RktSym">str</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">make-slow-matcher</span><span class="hspace"> </span><span class="RktSym">pattern-str</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">str</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=regexp.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._regexp-match%7E3f%2529%2529&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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">40000000</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">prev-thunk</span><span class="hspace"> </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&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">)</span><span class="hspace"> </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"> </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&rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace"> </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&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">prev-thunk</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">loop</span><span class="hspace"> </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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">)</span><span class="hspace"> </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&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktSym">loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">40000000</span><span class="RktPn">]</span><span class="hspace"> </span><span class="RktPn">[</span><span class="RktSym">prev-val</span><span class="hspace"> </span><span class="RktVal">#f</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">prev-thunk</span><span class="hspace"> </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&rel=lambda.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._lambda%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">lambda</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">)</span><span class="hspace"> </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"> </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&rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace"> </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&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktSym">prev-val</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">loop</span><span class="hspace"> </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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="hspace"> </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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktSym">n-loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">n</span><span class="hspace"> </span><span class="RktVal">400000</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace"> </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&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">done</span></td></tr><tr><td><span class="hspace"> </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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let</a></span><span class="hspace"> </span><span class="RktSym">m-loop</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">m</span><span class="hspace"> </span><span class="RktVal">100</span><span class="RktPn">]</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=if.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._if%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">if</a></span><span class="hspace"> </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&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._zero%7E3f%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">zero?</a></span><span class="hspace"> </span><span class="RktSym">m</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">n-loop</span><span class="hspace"> </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&rel=generic-numbers.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._sub1%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">sub1</a></span><span class="hspace"> </span><span class="RktSym">n</span><span class="RktPn">)</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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 "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""Reachability and Garbage Collection"">19.13<tt> </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&rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._make-weak-box%2529%2529&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&rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._weak-box-value%2529%2529&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&rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._weak-box-value%2529%2529&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"> </span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=index.html&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&rel=define-struct.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._struct%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">struct</a></span><span class="hspace"> </span><span class="RktSym">fish</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">weight</span><span class="hspace"> </span><span class="RktSym">color</span><span class="RktPn">)</span><span class="hspace"> </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&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fish</span><span class="hspace"> </span><span class="RktVal">7</span><span class="hspace"> </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&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">b</span><span class="hspace"> </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&rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._make-weak-box%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">make-weak-box</a></span><span class="hspace"> </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&rel=Writing.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._printf%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">printf</a></span><span class="hspace"> </span><span class="RktVal">"b has ~s\n"</span><span class="hspace"> </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&rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._weak-box-value%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">weak-box-value</a></span><span class="hspace"> </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&rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&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"> </span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=index.html&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&rel=define-struct.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._struct%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">struct</a></span><span class="hspace"> </span><span class="RktSym">fish</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">weight</span><span class="hspace"> </span><span class="RktSym">color</span><span class="RktPn">)</span><span class="hspace"> </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&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fish</span><span class="hspace"> </span><span class="RktVal">7</span><span class="hspace"> </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&rel=define.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fbase..rkt%2529._define%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">define</a></span><span class="hspace"> </span><span class="RktSym">b</span><span class="hspace"> </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&rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._make-weak-box%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">make-weak-box</a></span><span class="hspace"> </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&rel=Writing.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._printf%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">printf</a></span><span class="hspace"> </span><span class="RktVal">"b has ~s\n"</span><span class="hspace"> </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&rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._weak-box-value%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">weak-box-value</a></span><span class="hspace"> </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&rel=set_.html%23%2528form._%2528%2528quote._%7E23%7E25kernel%2529._set%2521%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">set!</a></span><span class="hspace"> </span><span class="RktSym">f</span><span class="hspace"> </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&rel=number-types.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._fixnum%7E3f%2529%2529&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 "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""Weak_Boxes_and_Testing"">19.14<tt> </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’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"> </span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=index.html&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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%252A%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let*</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">fishes</span><span class="hspace"> </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&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fish</span><span class="hspace"> </span><span class="RktVal">8</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">red</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fish</span><span class="hspace"> </span><span class="RktVal">7</span><span class="hspace"> </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"> </span><span class="RktPn">[</span><span class="RktSym">wb</span><span class="hspace"> </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&rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._make-weak-box%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">make-weak-box</a></span><span class="hspace"> </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&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list-ref%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">list-ref</a></span><span class="hspace"> </span><span class="RktSym">fishes</span><span class="hspace"> </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"> </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&rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">collect-garbage</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=Writing.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._printf%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">printf</a></span><span class="hspace"> </span><span class="RktVal">"still there? ~s\n"</span><span class="hspace"> </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"> </span><a href="https://download.racket-lang.org/releases/8.6/doc/local-redirect/index.html?doc=reference&rel=index.html&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&rel=let.html%23%2528form._%2528%2528lib._racket%252Fprivate%252Fletstx-scheme..rkt%2529._let%252A%2529%2529&version=8.6" class="RktStxLink Sq" data-pltdoc="x">let*</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktPn">[</span><span class="RktSym">fishes</span><span class="hspace"> </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&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">list</a></span><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fish</span><span class="hspace"> </span><span class="RktVal">8</span><span class="hspace"> </span><span class="RktVal">'</span><span class="RktVal">red</span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </span><span class="RktPn">(</span><span class="RktSym">fish</span><span class="hspace"> </span><span class="RktVal">7</span><span class="hspace"> </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"> </span><span class="RktPn">[</span><span class="RktSym">wb</span><span class="hspace"> </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&rel=weakbox.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._make-weak-box%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">make-weak-box</a></span><span class="hspace"> </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&rel=pairs.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._list-ref%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">list-ref</a></span><span class="hspace"> </span><span class="RktSym">fishes</span><span class="hspace"> </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"> </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&rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">collect-garbage</a></span><span class="RktPn">)</span></td></tr><tr><td><span class="hspace"> </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&rel=Writing.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._printf%2529%2529&version=8.6" class="RktValLink Sq" data-pltdoc="x">printf</a></span><span class="hspace"> </span><span class="RktVal">"still there? ~s\n"</span><span class="hspace"> </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 "scribblings/guide/guide.scrbl")" x-source-pkg="racket-doc" x-part-tag=""Reducing_Garbage_Collection_Pauses"">19.15<tt> </tt><a name="(part._.Reducing_.Garbage_.Collection_.Pauses)"></a>Reducing Garbage Collection Pauses</h4><p>By default, Racket’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’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>’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’s work has been performed by minor collections
|
||
|
the time that a major collection is needed, so the major
|
||
|
collection’s pause is as short as a minor collection’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>’s incremental mode, objects are never promoted out
|
||
|
of the category of “recently allocated,” although there are
|
||
|
degrees of “recently” 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&rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&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&rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&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&rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&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&rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&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&rel=garbagecollection.html%23%2528def._%2528%2528quote._%7E23%7E25kernel%2529._collect-garbage%2529%2529&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"> </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, "8.6", "../");"/></form> <a href="https://download.racket-lang.org/releases/8.6/doc/index.html" title="up to the documentation top" data-pltdoc="x" onclick="return GotoPLTRoot("8.6");">top</a><span class="tocsettoggle"> <a href="javascript:void(0);" title="show/hide table of contents" onclick="TocsetToggle();">contents</a></span></span><span class="navright"> <a href="concurrency.html" title="backward to "18 Concurrency and Synchronization"" data-pltdoc="x">← prev</a> <a href="index.html" title="up to "The Racket Guide"" data-pltdoc="x">up</a> <a href="parallelism.html" title="forward to "20 Parallelism"" data-pltdoc="x">next →</a></span> </div></div></div><div id="contextindicator"> </div></body></html>
|