mirror of
https://github.com/bspeice/speice.io
synced 2024-11-14 05:58:09 -05:00
2187 lines
835 KiB
XML
2187 lines
835 KiB
XML
<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="rss.xsl"?>
|
||
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
|
||
<channel>
|
||
<title>The Old Speice Guy Blog</title>
|
||
<link>https://speice.io/</link>
|
||
<description>The Old Speice Guy Blog</description>
|
||
<lastBuildDate>Sun, 20 Nov 2022 12:00:00 GMT</lastBuildDate>
|
||
<docs>https://validator.w3.org/feed/docs/rss2.html</docs>
|
||
<generator>https://github.com/jpmonette/feed</generator>
|
||
<language>en</language>
|
||
<item>
|
||
<title><![CDATA[The webpack industrial complex]]></title>
|
||
<link>https://speice.io/2011/11/webpack-industrial-complex</link>
|
||
<guid>https://speice.io/2011/11/webpack-industrial-complex</guid>
|
||
<pubDate>Sun, 20 Nov 2022 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[This started because I wanted to build a synthesizer. Setting a goal of "digital DX7" was ambitious, but I needed something unrelated to the day job. Beyond that, working with audio seemed like a good challenge. I enjoy performance-focused code, and performance problems in audio are conspicuous. Building a web project was an obvious choice because of the web audio API documentation and independence from a large Digital Audio Workstation (DAW).]]></description>
|
||
<content:encoded><![CDATA[<p>This started because I wanted to build a synthesizer. Setting a goal of "digital DX7" was ambitious, but I needed something unrelated to the day job. Beyond that, working with audio seemed like a good challenge. I enjoy performance-focused code, and performance problems in audio are conspicuous. Building a web project was an obvious choice because of the web audio API documentation and independence from a large Digital Audio Workstation (DAW).</p>
|
||
<p>The project was soon derailed trying to sort out technical issues unrelated to the original purpose. Finding a resolution was a frustrating journey, and it's still not clear whether those problems were my fault. As a result, I'm writing this to try making sense of it, as a case study/reference material, and to salvage something from the process.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="starting-strong">Starting strong<a href="https://speice.io/2011/11/webpack-industrial-complex#starting-strong" class="hash-link" aria-label="Direct link to Starting strong" title="Direct link to Starting strong"></a></h2>
|
||
<p>The sole starting requirement was to write everything in TypeScript. Not because of project scale, but because guardrails help with unfamiliar territory. Keeping that in mind, the first question was: how does one start a new project? All I actually need is "compile TypeScript, show it in a browser."</p>
|
||
<p>Create React App (CRA) came to the rescue and the rest of that evening was a joy. My TypeScript/JavaScript skills were rusty, but the online documentation was helpful. I had never understood the appeal of JSX (why put a DOM in JavaScript?) until it made connecting an <code>onEvent</code> handler and a function easy.</p>
|
||
<p>Some quick dimensional analysis later and there was a sine wave oscillator playing A=440 through the speakers. I specifically remember thinking "modern browsers are magical."</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="continuing-on">Continuing on<a href="https://speice.io/2011/11/webpack-industrial-complex#continuing-on" class="hash-link" aria-label="Direct link to Continuing on" title="Direct link to Continuing on"></a></h2>
|
||
<p>Now comes the first mistake: I began to worry about "scale" before encountering an actual problem. Rather than rendering audio in the main thread, why not use audio worklets and render in a background thread instead?</p>
|
||
<p>The first sign something was amiss came from the TypeScript compiler errors showing the audio worklet API <a href="https://github.com/microsoft/TypeScript/issues/28308" target="_blank" rel="noopener noreferrer">was missing</a>. After searching out Github issues and (unsuccessfully) tweaking the <code>.tsconfig</code> settings, I settled on installing a package and moving on.</p>
|
||
<p>The next problem came from actually using the API. Worklets must load from separate "modules," but it wasn't clear how to guarantee the worklet code stayed separate from the application. I saw recommendations to use <code>new URL(<local path>, import.meta.url)</code> and it worked! Well, kind of:</p>
|
||
<p><img decoding="async" loading="lazy" alt="Browser error" src="https://speice.io/assets/images/video_mp2t-1decc5fbd88b54dadd06691ce4c629ec.png" width="1279" height="143" class="img_ev3q"></p>
|
||
<p>That file has the audio processor code, so why does it get served with <code>Content-Type: video/mp2t</code>?</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="floundering-about">Floundering about<a href="https://speice.io/2011/11/webpack-industrial-complex#floundering-about" class="hash-link" aria-label="Direct link to Floundering about" title="Direct link to Floundering about"></a></h2>
|
||
<p>Now comes the second mistake: even though I didn't understand the error, I ignored recommendations to <a href="https://hackernoon.com/implementing-audioworklets-with-react-8a80a470474" target="_blank" rel="noopener noreferrer">just use JavaScript</a> and stuck by the original TypeScript requirement.</p>
|
||
<p>I tried different project structures. Moving the worklet code to a new folder didn't help, nor did setting up a monorepo and placing it in a new package.</p>
|
||
<p>I tried three different CRA tools - <code>react-app-rewired</code>, <code>craco</code>, <code>customize-react-app</code> - but got the same problem. Each has varying levels of compatibility with recent CRA versions, so it wasn't clear if I had the right solution but implemented it incorrectly. After attempting to eject the application and panicking after seeing the configuration, I abandoned that as well.</p>
|
||
<p>I tried changing the webpack configuration: using <a href="https://github.com/webpack/webpack/issues/11543#issuecomment-917673256" target="_blank" rel="noopener noreferrer">new</a> <a href="https://github.com/popelenkow/worker-url" target="_blank" rel="noopener noreferrer">loaders</a>, setting <a href="https://github.com/webpack/webpack/discussions/14093#discussioncomment-1257149" target="_blank" rel="noopener noreferrer">asset rules</a>, even <a href="https://github.com/webpack/webpack/issues/11543#issuecomment-826897590" target="_blank" rel="noopener noreferrer">changing how webpack detects worker resources</a>. In hindsight, entry points may have been the answer. But because CRA actively resists attempts to change its webpack configuration, and I couldn't find audio worklet examples in any other framework, I gave up.</p>
|
||
<p>I tried so many application frameworks. Next.js looked like a good candidate, but added its own <a href="https://github.com/vercel/next.js/issues/24907" target="_blank" rel="noopener noreferrer">bespoke webpack complexity</a> to the existing confusion. Astro had the best "getting started" experience, but I refuse to install an IDE-specific plugin. I first used Deno while exploring Lume, but it couldn't import the audio worklet types (maybe because of module compatibility?). Each framework was unique in its own way (shout-out to SvelteKit) but I couldn't figure out how to make them work.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="learning-and-reflecting">Learning and reflecting<a href="https://speice.io/2011/11/webpack-industrial-complex#learning-and-reflecting" class="hash-link" aria-label="Direct link to Learning and reflecting" title="Direct link to Learning and reflecting"></a></h2>
|
||
<p>I ended up using Vite and vite-plugin-react-pages to handle both "build the app" and "bundle worklets," but the specific tool choice isn't important. Instead, the focus should be on lessons learned.</p>
|
||
<p>For myself:</p>
|
||
<ul>
|
||
<li>I'm obsessed with tooling, to the point it can derail the original goal. While it comes from a good place (for example: "types are awesome"), it can get in the way of more important work</li>
|
||
<li>I tend to reach for online resources right after seeing a new problem. While finding help online is often faster, spending time understanding the problem would have been more productive than cycling through (often outdated) blog posts</li>
|
||
</ul>
|
||
<p>For the tools:</p>
|
||
<ul>
|
||
<li>Resource bundling is great and solves a genuine challenge. I've heard too many horror stories of developers writing modules by hand to believe this is unnecessary complexity</li>
|
||
<li>Webpack is a build system and modern frameworks are deeply dependent on it (hence the "webpack industrial complex"). While this often saves users from unnecessary complexity, there's no path forward if something breaks</li>
|
||
<li>There's little ability to mix and match tools across frameworks. Next.js and Gatsby let users extend webpack, but because each framework adds its own modules, changes aren't portable. After spending a week looking at webpack, I had an example running with parcel in thirty minutes, but couldn't integrate it</li>
|
||
</ul>
|
||
<p>In the end, learning new systems is fun, but a focus on tools that "just work" can leave users out in the cold if they break down.</p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[Release the GIL]]></title>
|
||
<link>https://speice.io/2019/12/release-the-gil</link>
|
||
<guid>https://speice.io/2019/12/release-the-gil</guid>
|
||
<pubDate>Sat, 14 Dec 2019 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[Complaining about the Global Interpreter Lock]]></description>
|
||
<content:encoded><![CDATA[<p>Complaining about the <a href="https://wiki.python.org/moin/GlobalInterpreterLock" target="_blank" rel="noopener noreferrer">Global Interpreter Lock</a>
|
||
(GIL) seems like a rite of passage for Python developers. It's easy to criticize a design decision
|
||
made before multi-core CPU's were widely available, but the fact that it's still around indicates
|
||
that it generally works <a href="https://wiki.c2.com/?PrematureOptimization" target="_blank" rel="noopener noreferrer">Good</a>
|
||
<a href="https://wiki.c2.com/?YouArentGonnaNeedIt" target="_blank" rel="noopener noreferrer">Enough</a>. Besides, there are simple and effective
|
||
workarounds; it's not hard to start a
|
||
<a href="https://docs.python.org/3/library/multiprocessing.html" target="_blank" rel="noopener noreferrer">new process</a> and use message passing to
|
||
synchronize code running in parallel.</p>
|
||
<p>Still, wouldn't it be nice to have more than a single active interpreter thread? In an age of
|
||
asynchronicity and <em>M:N</em> threading, Python seems lacking. The ideal scenario is to take advantage of
|
||
both Python's productivity and the modern CPU's parallel capabilities.</p>
|
||
<p>Presented below are two strategies for releasing the GIL's icy grip without giving up on what makes
|
||
Python a nice language to start with. Bear in mind: these are just the tools, no claim is made about
|
||
whether it's a good idea to use them. Very often, unlocking the GIL is an
|
||
<a href="https://en.wikipedia.org/wiki/XY_problem" target="_blank" rel="noopener noreferrer">XY problem</a>; you want application performance, and the
|
||
GIL seems like an obvious bottleneck. Remember that any gains from running code in parallel come at
|
||
the expense of project complexity; messing with the GIL is ultimately messing with Python's memory
|
||
model.</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token plain">load_ext Cython</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">from</span><span class="token plain"> numba </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">import</span><span class="token plain"> jit</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">N </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1_000_000_000</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="cython">Cython<a href="https://speice.io/2019/12/release-the-gil#cython" class="hash-link" aria-label="Direct link to Cython" title="Direct link to Cython"></a></h2>
|
||
<p>Put simply, <a href="https://cython.org/" target="_blank" rel="noopener noreferrer">Cython</a> is a programming language that looks a lot like Python,
|
||
gets <a href="https://en.wikipedia.org/wiki/Source-to-source_compiler" target="_blank" rel="noopener noreferrer">transpiled</a> to C/C++, and integrates
|
||
well with the <a href="https://en.wikipedia.org/wiki/CPython" target="_blank" rel="noopener noreferrer">CPython</a> API. It's great for building Python
|
||
wrappers to C and C++ libraries, writing optimized code for numerical processing, and tons more. And
|
||
when it comes to managing the GIL, there are two special features:</p>
|
||
<ul>
|
||
<li>The <code>nogil</code>
|
||
<a href="https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#declaring-a-function-as-callable-without-the-gil" target="_blank" rel="noopener noreferrer">function annotation</a>
|
||
asserts that a Cython function is safe to use without the GIL, and compilation will fail if it
|
||
interacts with Python in an unsafe manner</li>
|
||
<li>The <code>with nogil</code>
|
||
<a href="https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#releasing-the-gil" target="_blank" rel="noopener noreferrer">context manager</a>
|
||
explicitly unlocks the CPython GIL while active</li>
|
||
</ul>
|
||
<p>Whenever Cython code runs inside a <code>with nogil</code> block on a separate thread, the Python interpreter
|
||
is unblocked and allowed to continue work elsewhere. We'll define a "busy work" function that
|
||
demonstrates this principle in action:</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token plain">cython</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Annotating a function with `nogil` indicates only that it is safe</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># to call in a `with nogil` block. It *does not* release the GIL.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">cdef unsigned </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">long</span><span class="token plain"> fibonacci</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">unsigned </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">long</span><span class="token plain"> n</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> nogil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">if</span><span class="token plain"> n </span><span class="token operator" style="color:hsl(221, 87%, 60%)"><=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> n</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> cdef unsigned </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">long</span><span class="token plain"> a </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> b </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> c </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> c </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> a </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">for</span><span class="token plain"> _i </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">in</span><span class="token plain"> </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">range</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> n</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> a </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> b </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> c</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> c </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> a </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> c</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">def</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">cython_nogil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">unsigned </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">long</span><span class="token plain"> n</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Explicitly release the GIL while running `fibonacci`</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">with</span><span class="token plain"> nogil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> value </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> fibonacci</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">n</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> value</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">def</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">cython_gil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">unsigned </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">long</span><span class="token plain"> n</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Because the GIL is not explicitly released, it implicitly</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># remains acquired when running the `fibonacci` function</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> fibonacci</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">n</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>First, let's time how long it takes Cython to calculate the billionth Fibonacci number:</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token plain">time</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">_ </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> cython_gil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<blockquote>
|
||
<pre><p>CPU times: user 365 ms, sys: 0 ns, total: 365 ms
|
||
Wall time: 372 ms</p></pre>
|
||
</blockquote>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token plain">time</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">_ </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> cython_nogil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<blockquote>
|
||
<pre><p>CPU times: user 381 ms, sys: 0 ns, total: 381 ms
|
||
Wall time: 388 ms</p></pre>
|
||
</blockquote>
|
||
<p>Both versions (with and without GIL) take effectively the same amount of time to run. Even when
|
||
running this calculation in parallel on separate threads, it is expected that the run time will
|
||
double because only one thread can be active at a time:</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token plain">time</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">from</span><span class="token plain"> threading </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">import</span><span class="token plain"> Thread</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Create the two threads to run on</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> Thread</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">cython_gil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> args</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> Thread</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">cython_gil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> args</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Start the threads</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">start</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> t2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">start</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Wait for the threads to finish</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> t2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<blockquote>
|
||
<pre><p>CPU times: user 641 ms, sys: 5.62 ms, total: 647 ms
|
||
Wall time: 645 ms</p></pre>
|
||
</blockquote>
|
||
<p>However, if the first thread releases the GIL, the second thread is free to acquire it and run in
|
||
parallel:</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token plain">time</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> Thread</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">cython_nogil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> args</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> Thread</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">cython_gil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> args</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">start</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> t2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">start</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> t2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<blockquote>
|
||
<pre><p>CPU times: user 717 ms, sys: 372 µs, total: 718 ms
|
||
Wall time: 358 ms</p></pre>
|
||
</blockquote>
|
||
<p>Because <code>user</code> time represents the sum of processing time on all threads, it doesn't change much.
|
||
The <a href="https://en.wikipedia.org/wiki/Elapsed_real_time" target="_blank" rel="noopener noreferrer">"wall time"</a> has been cut roughly in half
|
||
because each function is running simultaneously.</p>
|
||
<p>Keep in mind that the <strong>order in which threads are started</strong> makes a difference!</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token plain">time</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Note that the GIL-locked version is started first</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> Thread</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">cython_gil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> args</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> Thread</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">cython_nogil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> args</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">start</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> t2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">start</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> t2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<blockquote>
|
||
<pre><p>CPU times: user 667 ms, sys: 0 ns, total: 667 ms
|
||
Wall time: 672 ms</p></pre>
|
||
</blockquote>
|
||
<p>Even though the second thread releases the GIL while running, it can't start until the first has
|
||
completed. Thus, the overall runtime is effectively the same as running two GIL-locked threads.</p>
|
||
<p>Finally, be aware that attempting to unlock the GIL from a thread that doesn't own it will crash the
|
||
<strong>interpreter</strong>, not just the thread attempting the unlock:</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token plain">cython</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">cdef </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">int</span><span class="token plain"> cython_recurse</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token builtin" style="color:hsl(119, 34%, 47%)">int</span><span class="token plain"> n</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> nogil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">if</span><span class="token plain"> n </span><span class="token operator" style="color:hsl(221, 87%, 60%)"><=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">with</span><span class="token plain"> nogil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> cython_recurse</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">n </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">cython_recurse</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<blockquote>
|
||
<pre><p>Fatal Python error: PyEval_SaveThread: NULL tstate</p><p>Thread 0x00007f499effd700 (most recent call first):
|
||
File "/home/bspeice/.virtualenvs/release-the-gil/lib/python3.7/site-packages/ipykernel/parentpoller.py", line 39 in run
|
||
File "/usr/lib/python3.7/threading.py", line 926 in _bootstrap_inner
|
||
File "/usr/lib/python3.7/threading.py", line 890 in _bootstrap</p></pre>
|
||
</blockquote>
|
||
<p>In practice, avoiding this issue is simple. First, <code>nogil</code> functions probably shouldn't contain
|
||
<code>with nogil</code> blocks. Second, Cython can
|
||
<a href="https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#conditional-acquiring-releasing-the-gil" target="_blank" rel="noopener noreferrer">conditionally acquire/release</a>
|
||
the GIL, so these conditions can be used to synchronize access. Finally, Cython's documentation for
|
||
<a href="https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html#acquiring-and-releasing-the-gil" target="_blank" rel="noopener noreferrer">external C code</a>
|
||
contains more detail on how to safely manage the GIL.</p>
|
||
<p>To conclude: use Cython's <code>nogil</code> annotation to assert that functions are safe for calling when the
|
||
GIL is unlocked, and <code>with nogil</code> to actually unlock the GIL and run those functions.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="numba">Numba<a href="https://speice.io/2019/12/release-the-gil#numba" class="hash-link" aria-label="Direct link to Numba" title="Direct link to Numba"></a></h2>
|
||
<p>Like Cython, <a href="https://numba.pydata.org/" target="_blank" rel="noopener noreferrer">Numba</a> is a "compiled Python." Where Cython works by
|
||
compiling a Python-like language to C/C++, Numba compiles Python bytecode <em>directly to machine code</em>
|
||
at runtime. Behavior is controlled with a special <code>@jit</code> decorator; calling a decorated function
|
||
first compiles it to machine code before running. Calling the function a second time re-uses that
|
||
machine code unless the argument types have changed.</p>
|
||
<p>Numba works best when a <code>nopython=True</code> argument is added to the <code>@jit</code> decorator; functions
|
||
compiled in <a href="http://numba.pydata.org/numba-doc/latest/user/jit.html?#nopython" target="_blank" rel="noopener noreferrer"><code>nopython</code></a> mode
|
||
avoid the CPython API and have performance comparable to C. Further, adding <code>nogil=True</code> to the
|
||
<code>@jit</code> decorator unlocks the GIL while that function is running. Note that <code>nogil</code> and <code>nopython</code>
|
||
are separate arguments; while it is necessary for code to be compiled in <code>nopython</code> mode in order to
|
||
release the lock, the GIL will remain locked if <code>nogil=False</code> (the default).</p>
|
||
<p>Let's repeat the same experiment, this time using Numba instead of Cython:</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># The `int` type annotation is only for humans and is ignored</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># by Numba.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token decorator annotation punctuation" style="color:hsl(119, 34%, 47%)">@jit</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">nopython</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token boolean" style="color:hsl(35, 99%, 36%)">True</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> nogil</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token boolean" style="color:hsl(35, 99%, 36%)">True</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">def</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">numba_nogil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">n</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">int</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">int</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">if</span><span class="token plain"> n </span><span class="token operator" style="color:hsl(221, 87%, 60%)"><=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> n</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> a </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> b </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> c </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> a </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">for</span><span class="token plain"> _i </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">in</span><span class="token plain"> </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">range</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> n</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> a </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> b </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> c</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> c </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> a </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> c</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Run using `nopython` mode to receive a performance boost,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># but GIL remains locked due to `nogil=False` by default.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token decorator annotation punctuation" style="color:hsl(119, 34%, 47%)">@jit</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">nopython</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token boolean" style="color:hsl(35, 99%, 36%)">True</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">def</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">numba_gil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">n</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">int</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">int</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">if</span><span class="token plain"> n </span><span class="token operator" style="color:hsl(221, 87%, 60%)"><=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> n</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> a </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> b </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> c </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> a </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">for</span><span class="token plain"> _i </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">in</span><span class="token plain"> </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">range</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> n</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> a </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> b </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> c</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> c </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> a </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+</span><span class="token plain"> b</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> c</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Call each function once to force compilation; we don't want</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)"># the timing statistics to include how long it takes to compile.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">numba_nogil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">numba_gil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>We'll perform the same tests as above; first, figure out how long it takes the function to run:</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token plain">time</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">_ </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> numba_gil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<blockquote>
|
||
<pre><p>CPU times: user 253 ms, sys: 258 µs, total: 253 ms
|
||
Wall time: 251 ms</p></pre>
|
||
</blockquote>
|
||
<small></small><p><small>Aside: it's not immediately clear why Numba takes ~20% less time to run than Cython for code that should be
|
||
effectively identical after compilation.</small>
|
||
</p><p>When running two GIL-locked threads, the result (as expected) takes around twice as long to compute:</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token plain">time</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> Thread</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">numba_gil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> args</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> Thread</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">numba_gil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> args</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">start</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> t2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">start</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> t2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<blockquote>
|
||
<pre><p>CPU times: user 541 ms, sys: 3.96 ms, total: 545 ms
|
||
Wall time: 541 ms</p></pre>
|
||
</blockquote>
|
||
<p>But if the GIL-unlocking thread starts first, both threads run in parallel:</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token plain">time</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> Thread</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">numba_nogil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> args</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> Thread</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">numba_gil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> args</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">start</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> t2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">start</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> t2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<blockquote>
|
||
<pre><p>CPU times: user 551 ms, sys: 7.77 ms, total: 559 ms
|
||
Wall time: 279 ms</p></pre>
|
||
</blockquote>
|
||
<p>Just like Cython, starting the GIL-locked thread first leads to poor performance:</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token operator" style="color:hsl(221, 87%, 60%)">%</span><span class="token plain">time</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> Thread</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">numba_gil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> args</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> Thread</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">numba_nogil</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> args</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain">N</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">start</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> t2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">start</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">t1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> t2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<blockquote>
|
||
<pre><p>CPU times: user 524 ms, sys: 0 ns, total: 524 ms
|
||
Wall time: 522 ms</p></pre>
|
||
</blockquote>
|
||
<p>Finally, unlike Cython, Numba will unlock the GIL if and only if it is currently acquired;
|
||
recursively calling <code>@jit(nogil=True)</code> functions is perfectly safe:</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">from</span><span class="token plain"> numba </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">import</span><span class="token plain"> jit</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token decorator annotation punctuation" style="color:hsl(119, 34%, 47%)">@jit</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">nopython</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token boolean" style="color:hsl(35, 99%, 36%)">True</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> nogil</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token boolean" style="color:hsl(35, 99%, 36%)">True</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">def</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">numba_recurse</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">n</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">int</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">int</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">if</span><span class="token plain"> n </span><span class="token operator" style="color:hsl(221, 87%, 60%)"><=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> numba_recurse</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">n </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">numba_recurse</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://speice.io/2019/12/release-the-gil#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion"></a></h2>
|
||
<p>Before finishing, it's important to address pain points that will show up if these techniques are
|
||
used in a more realistic project:</p>
|
||
<p>First, code running in a GIL-free context will likely also need non-trivial data structures;
|
||
GIL-free functions aren't useful if they're constantly interacting with Python objects whose access
|
||
requires the GIL. Cython provides
|
||
<a href="http://docs.cython.org/en/latest/src/tutorial/cdef_classes.html" target="_blank" rel="noopener noreferrer">extension types</a> and Numba
|
||
provides a <a href="https://numba.pydata.org/numba-doc/dev/user/jitclass.html" target="_blank" rel="noopener noreferrer"><code>@jitclass</code></a> decorator to
|
||
address this need.</p>
|
||
<p>Second, building and distributing applications that make use of Cython/Numba can be complicated.
|
||
Cython packages require running the compiler, (potentially) linking/packaging external dependencies,
|
||
and distributing a binary wheel. Numba is generally simpler because the code being distributed is
|
||
pure Python, but can be tricky since errors aren't detected until runtime.</p>
|
||
<p>Finally, while unlocking the GIL is often a solution in search of a problem, both Cython and Numba
|
||
provide tools to directly manage the GIL when appropriate. This enables true parallelism (not just
|
||
<a href="https://stackoverflow.com/a/1050257" target="_blank" rel="noopener noreferrer">concurrency</a>) that is impossible in vanilla Python.</p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[Binary format shootout]]></title>
|
||
<link>https://speice.io/2019/09/binary-format-shootout</link>
|
||
<guid>https://speice.io/2019/09/binary-format-shootout</guid>
|
||
<pubDate>Sat, 28 Sep 2019 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[I've found that in many personal projects,]]></description>
|
||
<content:encoded><![CDATA[<p>I've found that in many personal projects,
|
||
<a href="https://en.wikipedia.org/wiki/Analysis_paralysis" target="_blank" rel="noopener noreferrer">analysis paralysis</a> is particularly deadly.
|
||
Making good decisions in the beginning avoids pain and suffering later; if extra research prevents
|
||
future problems, I'm happy to continue <del>procrastinating</del> researching indefinitely.</p>
|
||
<p>So let's say you're in need of a binary serialization format. Data will be going over the network,
|
||
not just in memory, so having a schema document and code generation is a must. Performance is
|
||
crucial, so formats that support zero-copy de/serialization are given priority. And the more
|
||
languages supported, the better; I use Rust, but can't predict what other languages this could
|
||
interact with.</p>
|
||
<p>Given these requirements, the candidates I could find were:</p>
|
||
<ol>
|
||
<li><a href="https://capnproto.org/" target="_blank" rel="noopener noreferrer">Cap'n Proto</a> has been around the longest, and is the most established</li>
|
||
<li><a href="https://google.github.io/flatbuffers/" target="_blank" rel="noopener noreferrer">Flatbuffers</a> is the newest, and claims to have a simpler
|
||
encoding</li>
|
||
<li><a href="https://github.com/real-logic/simple-binary-encoding" target="_blank" rel="noopener noreferrer">Simple Binary Encoding</a> has the simplest
|
||
encoding, but the Rust implementation is unmaintained</li>
|
||
</ol>
|
||
<p>Any one of these will satisfy the project requirements: easy to transmit over a network, reasonably
|
||
fast, and polyglot support. But how do you actually pick one? It's impossible to know what issues
|
||
will follow that choice, so I tend to avoid commitment until the last possible moment.</p>
|
||
<p>Still, a choice must be made. Instead of worrying about which is "the best," I decided to build a
|
||
small proof-of-concept system in each format and pit them against each other. All code can be found
|
||
in the <a href="https://github.com/speice-io/marketdata-shootout" target="_blank" rel="noopener noreferrer">repository</a> for this post.</p>
|
||
<p>We'll discuss more in detail, but a quick preview of the results:</p>
|
||
<ul>
|
||
<li>Cap'n Proto: Theoretically performs incredibly well, the implementation had issues</li>
|
||
<li>Flatbuffers: Has some quirks, but largely lived up to its "zero-copy" promises</li>
|
||
<li>SBE: Best median and worst-case performance, but the message structure has a limited feature set</li>
|
||
</ul>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="prologue-binary-parsing-with-nom">Prologue: Binary Parsing with Nom<a href="https://speice.io/2019/09/binary-format-shootout#prologue-binary-parsing-with-nom" class="hash-link" aria-label="Direct link to Prologue: Binary Parsing with Nom" title="Direct link to Prologue: Binary Parsing with Nom"></a></h2>
|
||
<p>Our benchmark system will be a simple data processor; given depth-of-book market data from
|
||
<a href="https://iextrading.com/trading/market-data/#deep" target="_blank" rel="noopener noreferrer">IEX</a>, serialize each message into the schema
|
||
format, read it back, and calculate total size of stock traded and the lowest/highest quoted prices.
|
||
This test isn't complex, but is representative of the project I need a binary format for.</p>
|
||
<p>But before we make it to that point, we have to actually read in the market data. To do so, I'm
|
||
using a library called <a href="https://github.com/Geal/nom" target="_blank" rel="noopener noreferrer"><code>nom</code></a>. Version 5.0 was recently released and
|
||
brought some big changes, so this was an opportunity to build a non-trivial program and get
|
||
familiar.</p>
|
||
<p>If you don't already know about <code>nom</code>, it's a "parser generator". By combining different smaller
|
||
parsers, you can assemble a parser to handle complex structures without writing tedious code by
|
||
hand. For example, when parsing
|
||
<a href="https://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html#rfc.section.3.3" target="_blank" rel="noopener noreferrer">PCAP files</a>:</p>
|
||
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> 0 1 2 3</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> +---------------------------------------------------------------+</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> 0 | Block Type = 0x00000006 |</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> +---------------------------------------------------------------+</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> 4 | Block Total Length |</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> 8 | Interface ID |</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">12 | Timestamp (High) |</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">16 | Timestamp (Low) |</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">20 | Captured Len |</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">24 | Packet Len |</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | Packet Data |</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | ... |</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>...you can build a parser in <code>nom</code> that looks like
|
||
<a href="https://github.com/speice-io/marketdata-shootout/blob/369613843d39cfdc728e1003123bf87f79422497/src/parsers.rs#L59-L93" target="_blank" rel="noopener noreferrer">this</a>:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">const</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">ENHANCED_PACKET</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">4</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token number" style="color:hsl(35, 99%, 36%)">0x06</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0x00</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0x00</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0x00</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">enhanced_packet_block</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">input</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">IResult</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> remaining</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> block_type</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> block_len</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> interface_id</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> timestamp_high</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> timestamp_low</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> captured_len</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> packet_len</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">tuple</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">tag</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token constant" style="color:hsl(35, 99%, 36%)">ENHANCED_PACKET</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> le_u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> le_u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> le_u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> le_u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> le_u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> le_u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">input</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token operator" style="color:hsl(221, 87%, 60%)">?</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">remaining</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> packet_data</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">take</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">captured_len</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">remaining</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token operator" style="color:hsl(221, 87%, 60%)">?</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ok</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">remaining</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> packet_data</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>While this example isn't too interesting, more complex formats (like IEX market data) are where
|
||
<a href="https://github.com/speice-io/marketdata-shootout/blob/369613843d39cfdc728e1003123bf87f79422497/src/iex.rs" target="_blank" rel="noopener noreferrer"><code>nom</code> really shines</a>.</p>
|
||
<p>Ultimately, because the <code>nom</code> code in this shootout was the same for all formats, we're not too
|
||
interested in its performance. Still, it's worth mentioning that building the market data parser was
|
||
actually fun; I didn't have to write tons of boring code by hand.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="capn-proto">Cap'n Proto<a href="https://speice.io/2019/09/binary-format-shootout#capn-proto" class="hash-link" aria-label="Direct link to Cap'n Proto" title="Direct link to Cap'n Proto"></a></h2>
|
||
<p>Now it's time to get into the meaty part of the story. Cap'n Proto was the first format I tried
|
||
because of how long it has supported Rust (thanks to <a href="https://github.com/dwrensha" target="_blank" rel="noopener noreferrer">dwrensha</a> for
|
||
maintaining the Rust port since
|
||
<a href="https://github.com/capnproto/capnproto-rust/releases/tag/rustc-0.10" target="_blank" rel="noopener noreferrer">2014!</a>). However, I had a ton
|
||
of performance concerns once I started using it.</p>
|
||
<p>To serialize new messages, Cap'n Proto uses a "builder" object. This builder allocates memory on the
|
||
heap to hold the message content, but because builders
|
||
<a href="https://github.com/capnproto/capnproto-rust/issues/111" target="_blank" rel="noopener noreferrer">can't be re-used</a>, we have to allocate a
|
||
new buffer for every single message. I was able to work around this with a
|
||
<a href="https://github.com/speice-io/marketdata-shootout/blob/369613843d39cfdc728e1003123bf87f79422497/src/capnp_runner.rs#L17-L51" target="_blank" rel="noopener noreferrer">special builder</a>
|
||
that could re-use the buffer, but it required reading through Cap'n Proto's
|
||
<a href="https://github.com/capnproto/capnproto-rust/blob/master/benchmark/benchmark.rs#L124-L156" target="_blank" rel="noopener noreferrer">benchmarks</a>
|
||
to find an example, and used
|
||
<a href="https://doc.rust-lang.org/std/mem/fn.transmute.html" target="_blank" rel="noopener noreferrer"><code>std::mem::transmute</code></a> to bypass Rust's borrow
|
||
checker.</p>
|
||
<p>The process of reading messages was better, but still had issues. Cap'n Proto has two message
|
||
encodings: a <a href="https://capnproto.org/encoding.html#packing" target="_blank" rel="noopener noreferrer">"packed"</a> representation, and an
|
||
"unpacked" version. When reading "packed" messages, we need a buffer to unpack the message into
|
||
before we can use it; Cap'n Proto allocates a new buffer for each message we unpack, and I wasn't
|
||
able to figure out a way around that. In contrast, the unpacked message format should be where Cap'n
|
||
Proto shines; its main selling point is that there's <a href="https://capnproto.org/" target="_blank" rel="noopener noreferrer">no decoding step</a>.
|
||
However, accomplishing zero-copy deserialization required code in the private API
|
||
(<a href="https://github.com/capnproto/capnproto-rust/issues/148" target="_blank" rel="noopener noreferrer">since fixed</a>), and we allocate a vector on
|
||
every read for the segment table.</p>
|
||
<p>In the end, I put in significant work to make Cap'n Proto as fast as possible, but there were too
|
||
many issues for me to feel comfortable using it long-term.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="flatbuffers">Flatbuffers<a href="https://speice.io/2019/09/binary-format-shootout#flatbuffers" class="hash-link" aria-label="Direct link to Flatbuffers" title="Direct link to Flatbuffers"></a></h2>
|
||
<p>This is the new kid on the block. After a
|
||
<a href="https://github.com/google/flatbuffers/pull/3894" target="_blank" rel="noopener noreferrer">first attempt</a> didn't pan out, official support
|
||
was <a href="https://github.com/google/flatbuffers/pull/4898" target="_blank" rel="noopener noreferrer">recently launched</a>. Flatbuffers intends to
|
||
address the same problems as Cap'n Proto: high-performance, polyglot, binary messaging. The
|
||
difference is that Flatbuffers claims to have a simpler wire format and
|
||
<a href="https://google.github.io/flatbuffers/flatbuffers_benchmarks.html" target="_blank" rel="noopener noreferrer">more flexibility</a>.</p>
|
||
<p>On the whole, I enjoyed using Flatbuffers; the <a href="https://crates.io/crates/flatc-rust" target="_blank" rel="noopener noreferrer">tooling</a> is
|
||
nice, and unlike Cap'n Proto, parsing messages was actually zero-copy and zero-allocation. However,
|
||
there were still some issues.</p>
|
||
<p>First, Flatbuffers (at least in Rust) can't handle nested vectors. This is a problem for formats
|
||
like the following:</p>
|
||
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">table Message {</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> symbol: string;</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">}</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">table MultiMessage {</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> messages:[Message];</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>We want to create a <code>MultiMessage</code> which contains a vector of <code>Message</code>, and each <code>Message</code> itself
|
||
contains a vector (the <code>string</code> type). I was able to work around this by
|
||
<a href="https://github.com/speice-io/marketdata-shootout/blob/e9d07d148bf36a211a6f86802b313c4918377d1b/src/flatbuffers_runner.rs#L83" target="_blank" rel="noopener noreferrer">caching <code>Message</code> elements</a>
|
||
in a <code>SmallVec</code> before building the final <code>MultiMessage</code>, but it was a painful process that I
|
||
believe contributed to poor serialization performance.</p>
|
||
<p>Second, streaming support in Flatbuffers seems to be something of an
|
||
<a href="https://github.com/google/flatbuffers/issues/3898" target="_blank" rel="noopener noreferrer">afterthought</a>. Where Cap'n Proto in Rust handles
|
||
reading messages from a stream as part of the API, Flatbuffers just sticks a <code>u32</code> at the front of
|
||
each message to indicate the size. Not specifically a problem, but calculating message size without
|
||
that tag is nigh on impossible.</p>
|
||
<p>Ultimately, I enjoyed using Flatbuffers, and had to do significantly less work to make it perform
|
||
well.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="simple-binary-encoding">Simple Binary Encoding<a href="https://speice.io/2019/09/binary-format-shootout#simple-binary-encoding" class="hash-link" aria-label="Direct link to Simple Binary Encoding" title="Direct link to Simple Binary Encoding"></a></h2>
|
||
<p>Support for SBE was added by the author of one of my favorite
|
||
<a href="https://web.archive.org/web/20190427124806/https://polysync.io/blog/session-types-for-hearty-codecs/" target="_blank" rel="noopener noreferrer">Rust blog posts</a>.
|
||
I've <a href="https://speice.io/2019/06/high-performance-systems">talked previously</a> about how important
|
||
variance is in high-performance systems, so it was encouraging to read about a format that
|
||
<a href="https://github.com/real-logic/simple-binary-encoding/wiki/Why-Low-Latency" target="_blank" rel="noopener noreferrer">directly addressed</a> my
|
||
concerns. SBE has by far the simplest binary format, but it does make some tradeoffs.</p>
|
||
<p>Both Cap'n Proto and Flatbuffers use <a href="https://capnproto.org/encoding.html#structs" target="_blank" rel="noopener noreferrer">message offsets</a>
|
||
to handle variable-length data, <a href="https://capnproto.org/language.html#unions" target="_blank" rel="noopener noreferrer">unions</a>, and various
|
||
other features. In contrast, messages in SBE are essentially
|
||
<a href="https://github.com/real-logic/simple-binary-encoding/blob/master/sbe-samples/src/main/resources/example-schema.xml" target="_blank" rel="noopener noreferrer">just structs</a>;
|
||
variable-length data is supported, but there's no union type.</p>
|
||
<p>As mentioned in the beginning, the Rust port of SBE works well, but is
|
||
<a href="https://users.rust-lang.org/t/zero-cost-abstraction-frontier-no-copy-low-allocation-ordered-decoding/11515/9" target="_blank" rel="noopener noreferrer">essentially unmaintained</a>.
|
||
However, if you don't need union types, and can accept that schemas are XML documents, it's still
|
||
worth using. SBE's implementation had the best streaming support of all formats I tested, and
|
||
doesn't trigger allocation during de/serialization.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="results">Results<a href="https://speice.io/2019/09/binary-format-shootout#results" class="hash-link" aria-label="Direct link to Results" title="Direct link to Results"></a></h2>
|
||
<p>After building a test harness
|
||
<a href="https://github.com/speice-io/marketdata-shootout/blob/master/src/capnp_runner.rs" target="_blank" rel="noopener noreferrer">for</a>
|
||
<a href="https://github.com/speice-io/marketdata-shootout/blob/master/src/flatbuffers_runner.rs" target="_blank" rel="noopener noreferrer">each</a>
|
||
<a href="https://github.com/speice-io/marketdata-shootout/blob/master/src/sbe_runner.rs" target="_blank" rel="noopener noreferrer">format</a>, it was
|
||
time to actually take them for a spin. I used
|
||
<a href="https://github.com/speice-io/marketdata-shootout/blob/master/run_shootout.sh" target="_blank" rel="noopener noreferrer">this script</a> to run
|
||
the benchmarks, and the raw results are
|
||
<a href="https://github.com/speice-io/marketdata-shootout/blob/master/shootout.csv" target="_blank" rel="noopener noreferrer">here</a>. All data reported
|
||
below is the average of 10 runs on a single day of IEX data. Results were validated to make sure
|
||
that each format parsed the data correctly.</p>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="serialization">Serialization<a href="https://speice.io/2019/09/binary-format-shootout#serialization" class="hash-link" aria-label="Direct link to Serialization" title="Direct link to Serialization"></a></h3>
|
||
<p>This test measures, on a
|
||
<a href="https://github.com/speice-io/marketdata-shootout/blob/master/src/main.rs#L268-L272" target="_blank" rel="noopener noreferrer">per-message basis</a>,
|
||
how long it takes to serialize the IEX message into the desired format and write to a pre-allocated
|
||
buffer.</p>
|
||
<table><thead><tr><th style="text-align:left">Schema</th><th style="text-align:left">Median</th><th style="text-align:left">99th Pctl</th><th style="text-align:left">99.9th Pctl</th><th style="text-align:left">Total</th></tr></thead><tbody><tr><td style="text-align:left">Cap'n Proto Packed</td><td style="text-align:left">413ns</td><td style="text-align:left">1751ns</td><td style="text-align:left">2943ns</td><td style="text-align:left">14.80s</td></tr><tr><td style="text-align:left">Cap'n Proto Unpacked</td><td style="text-align:left">273ns</td><td style="text-align:left">1828ns</td><td style="text-align:left">2836ns</td><td style="text-align:left">10.65s</td></tr><tr><td style="text-align:left">Flatbuffers</td><td style="text-align:left">355ns</td><td style="text-align:left">2185ns</td><td style="text-align:left">3497ns</td><td style="text-align:left">14.31s</td></tr><tr><td style="text-align:left">SBE</td><td style="text-align:left">91ns</td><td style="text-align:left">1535ns</td><td style="text-align:left">2423ns</td><td style="text-align:left">3.91s</td></tr></tbody></table>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="deserialization">Deserialization<a href="https://speice.io/2019/09/binary-format-shootout#deserialization" class="hash-link" aria-label="Direct link to Deserialization" title="Direct link to Deserialization"></a></h3>
|
||
<p>This test measures, on a
|
||
<a href="https://github.com/speice-io/marketdata-shootout/blob/master/src/main.rs#L294-L298" target="_blank" rel="noopener noreferrer">per-message basis</a>,
|
||
how long it takes to read the previously-serialized message and perform some basic aggregation. The
|
||
aggregation code is the same for each format, so any performance differences are due solely to the
|
||
format implementation.</p>
|
||
<table><thead><tr><th style="text-align:left">Schema</th><th style="text-align:left">Median</th><th style="text-align:left">99th Pctl</th><th style="text-align:left">99.9th Pctl</th><th style="text-align:left">Total</th></tr></thead><tbody><tr><td style="text-align:left">Cap'n Proto Packed</td><td style="text-align:left">539ns</td><td style="text-align:left">1216ns</td><td style="text-align:left">2599ns</td><td style="text-align:left">18.92s</td></tr><tr><td style="text-align:left">Cap'n Proto Unpacked</td><td style="text-align:left">366ns</td><td style="text-align:left">737ns</td><td style="text-align:left">1583ns</td><td style="text-align:left">12.32s</td></tr><tr><td style="text-align:left">Flatbuffers</td><td style="text-align:left">173ns</td><td style="text-align:left">421ns</td><td style="text-align:left">1007ns</td><td style="text-align:left">6.00s</td></tr><tr><td style="text-align:left">SBE</td><td style="text-align:left">116ns</td><td style="text-align:left">286ns</td><td style="text-align:left">659ns</td><td style="text-align:left">4.05s</td></tr></tbody></table>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://speice.io/2019/09/binary-format-shootout#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion"></a></h2>
|
||
<p>Building a benchmark turned out to be incredibly helpful in making a decision; because a "union"
|
||
type isn't important to me, I can be confident that SBE best addresses my needs.</p>
|
||
<p>While SBE was the fastest in terms of both median and worst-case performance, its worst case
|
||
performance was proportionately far higher than any other format. It seems to be that
|
||
de/serialization time scales with message size, but I'll need to do some more research to understand
|
||
what exactly is going on.</p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[On building high performance systems]]></title>
|
||
<link>https://speice.io/2019/06/high-performance-systems</link>
|
||
<guid>https://speice.io/2019/06/high-performance-systems</guid>
|
||
<pubDate>Mon, 01 Jul 2019 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[Prior to working in the trading industry, my assumption was that High Frequency Trading (HFT) is]]></description>
|
||
<content:encoded><![CDATA[<p>Prior to working in the trading industry, my assumption was that High Frequency Trading (HFT) is
|
||
made up of people who have access to secret techniques mortal developers could only dream of. There
|
||
had to be some secret art that could only be learned if one had an appropriately tragic backstory.</p>
|
||
<p><img decoding="async" loading="lazy" alt="Kung Fu fight" src="https://speice.io/assets/images/kung-fu-5715f30eef7bf3aaa26770b1247024dc.webp" width="426" height="240" class="img_ev3q"></p>
|
||
<blockquote>
|
||
<p>How I assumed HFT people learn their secret techniques</p>
|
||
</blockquote>
|
||
<p>How else do you explain people working on systems that complete the round trip of market data in to
|
||
orders out (a.k.a. tick-to-trade) consistently within
|
||
<a href="https://stackoverflow.com/a/22082528/1454178" target="_blank" rel="noopener noreferrer">750-800 nanoseconds</a>? In roughly the time it takes a
|
||
computer to access
|
||
<a href="https://people.eecs.berkeley.edu/~rcs/research/interactive_latency.html" target="_blank" rel="noopener noreferrer">main memory 8 times</a>,
|
||
trading systems are capable of reading the market data packets, deciding what orders to send, doing
|
||
risk checks, creating new packets for exchange-specific protocols, and putting those packets on the
|
||
wire.</p>
|
||
<p>Having now worked in the trading industry, I can confirm the developers aren't super-human; I've
|
||
made some simple mistakes at the very least. Instead, what shows up in public discussions is that
|
||
philosophy, not technique, separates high-performance systems from everything else.
|
||
Performance-critical systems don't rely on "this one cool C++ optimization trick" to make code fast
|
||
(though micro-optimizations have their place); there's a lot more to worry about than just the code
|
||
written for the project.</p>
|
||
<p>The framework I'd propose is this: <strong>If you want to build high-performance systems, focus first on
|
||
reducing performance variance</strong> (reducing the gap between the fastest and slowest runs of the same
|
||
code), <strong>and only look at average latency once variance is at an acceptable level</strong>.</p>
|
||
<p>Don't get me wrong, I'm a much happier person when things are fast. Computer goes from booting in 20
|
||
seconds down to 10 because I installed a solid-state drive? Awesome. But if every fifth day it takes
|
||
a full minute to boot because of corrupted sectors? Not so great. Average speed over the course of a
|
||
week is the same in each situation, but you're painfully aware of that minute when it happens. When
|
||
it comes to code, the principal is the same: speeding up a function by an average of 10 milliseconds
|
||
doesn't mean much if there's a 100ms difference between your fastest and slowest runs. When
|
||
performance matters, you need to respond quickly <em>every time</em>, not just in aggregate.
|
||
High-performance systems should first optimize for time variance. Once you're consistent at the time
|
||
scale you care about, then focus on improving average time.</p>
|
||
<p>This focus on variance shows up all the time in industry too (emphasis added in all quotes below):</p>
|
||
<ul>
|
||
<li>
|
||
<p>In <a href="https://business.nasdaq.com/market-tech/marketplaces/trading" target="_blank" rel="noopener noreferrer">marketing materials</a> for
|
||
NASDAQ's matching engine, the most performance-sensitive component of the exchange, dependability
|
||
is highlighted in addition to instantaneous metrics:</p>
|
||
<blockquote>
|
||
<p>Able to <strong>consistently sustain</strong> an order rate of over 100,000 orders per second at sub-40
|
||
microsecond average latency</p>
|
||
</blockquote>
|
||
</li>
|
||
<li>
|
||
<p>The <a href="https://github.com/real-logic/aeron" target="_blank" rel="noopener noreferrer">Aeron</a> message bus has this to say about performance:</p>
|
||
<blockquote>
|
||
<p>Performance is the key focus. Aeron is designed to be the highest throughput with the lowest and
|
||
<strong>most predictable latency possible</strong> of any messaging system</p>
|
||
</blockquote>
|
||
</li>
|
||
<li>
|
||
<p>The company PolySync, which is working on autonomous vehicles,
|
||
<a href="https://polysync.io/blog/session-types-for-hearty-codecs/" target="_blank" rel="noopener noreferrer">mentions why</a> they picked their
|
||
specific messaging format:</p>
|
||
<blockquote>
|
||
<p>In general, high performance is almost always desirable for serialization. But in the world of
|
||
autonomous vehicles, <strong>steady timing performance is even more important</strong> than peak throughput.
|
||
This is because safe operation is sensitive to timing outliers. Nobody wants the system that
|
||
decides when to slam on the brakes to occasionally take 100 times longer than usual to encode
|
||
its commands.</p>
|
||
</blockquote>
|
||
</li>
|
||
<li>
|
||
<p><a href="https://solarflare.com/" target="_blank" rel="noopener noreferrer">Solarflare</a>, which makes highly-specialized network hardware, points out
|
||
variance (jitter) as a big concern for
|
||
<a href="https://solarflare.com/electronic-trading/" target="_blank" rel="noopener noreferrer">electronic trading</a>:</p>
|
||
<blockquote>
|
||
<p>The high stakes world of electronic trading, investment banks, market makers, hedge funds and
|
||
exchanges demand the <strong>lowest possible latency and jitter</strong> while utilizing the highest
|
||
bandwidth and return on their investment.</p>
|
||
</blockquote>
|
||
</li>
|
||
</ul>
|
||
<p>And to further clarify: we're not discussing <em>total run-time</em>, but variance of total run-time. There
|
||
are situations where it's not reasonably possible to make things faster, and you'd much rather be
|
||
consistent. For example, trading firms use
|
||
<a href="https://sniperinmahwah.wordpress.com/2017/06/07/network-effects-part-i/" target="_blank" rel="noopener noreferrer">wireless networks</a> because
|
||
the speed of light through air is faster than through fiber-optic cables. There's still at <em>absolute
|
||
minimum</em> a <a href="http://tinyurl.com/y2vd7tn8" target="_blank" rel="noopener noreferrer">~33.76 millisecond</a> delay required to send data between,
|
||
say,
|
||
<a href="https://www.theice.com/market-data/connectivity-and-feeds/wireless/tokyo-chicago" target="_blank" rel="noopener noreferrer">Chicago and Tokyo</a>.
|
||
If a trading system in Chicago calls the function for "send order to Tokyo" and waits to see if a
|
||
trade occurs, there's a physical limit to how long that will take. In this situation, the focus is
|
||
on keeping variance of <em>additional processing</em> to a minimum, since speed of light is the limiting
|
||
factor.</p>
|
||
<p>So how does one go about looking for and eliminating performance variance? To tell the truth, I
|
||
don't think a systematic answer or flow-chart exists. There's no substitute for (A) building a deep
|
||
understanding of the entire technology stack, and (B) actually measuring system performance (though
|
||
(C) watching a lot of <a href="https://www.youtube.com/channel/UCMlGfpWw-RUdWX_JbLCukXg" target="_blank" rel="noopener noreferrer">CppCon</a> videos for
|
||
inspiration never hurt). Even then, every project cares about performance to a different degree; you
|
||
may need to build an entire
|
||
<a href="https://www.youtube.com/watch?v=NH1Tta7purM&feature=youtu.be&t=3015" target="_blank" rel="noopener noreferrer">replica production system</a> to
|
||
accurately benchmark at nanosecond precision, or you may be content to simply
|
||
<a href="https://www.youtube.com/watch?v=BD9cRbxWQx8&feature=youtu.be&t=1335" target="_blank" rel="noopener noreferrer">avoid garbage collection</a> in
|
||
your Java code.</p>
|
||
<p>Even though everyone has different needs, there are still common things to look for when trying to
|
||
isolate and eliminate variance. In no particular order, these are my focus areas when thinking about
|
||
high-performance systems:</p>
|
||
<p><strong>Update 2019-09-21</strong>: Added notes on <code>isolcpus</code> and <code>systemd</code> affinity.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="language-specific">Language-specific<a href="https://speice.io/2019/06/high-performance-systems#language-specific" class="hash-link" aria-label="Direct link to Language-specific" title="Direct link to Language-specific"></a></h2>
|
||
<p><strong>Garbage Collection</strong>: How often does garbage collection happen? When is it triggered? What are the
|
||
impacts?</p>
|
||
<ul>
|
||
<li><a href="https://rushter.com/blog/python-garbage-collector/" target="_blank" rel="noopener noreferrer">In Python</a>, individual objects are collected
|
||
if the reference count reaches 0, and each generation is collected if
|
||
<code>num_alloc - num_dealloc > gc_threshold</code> whenever an allocation happens. The GIL is acquired for
|
||
the duration of generational collection.</li>
|
||
<li>Java has
|
||
<a href="https://docs.oracle.com/en/java/javase/12/gctuning/parallel-collector1.html#GUID-DCDD6E46-0406-41D1-AB49-FB96A50EB9CE" target="_blank" rel="noopener noreferrer">many</a>
|
||
<a href="https://docs.oracle.com/en/java/javase/12/gctuning/garbage-first-garbage-collector.html#GUID-ED3AB6D3-FD9B-4447-9EDF-983ED2F7A573" target="_blank" rel="noopener noreferrer">different</a>
|
||
<a href="https://docs.oracle.com/en/java/javase/12/gctuning/garbage-first-garbage-collector-tuning.html#GUID-90E30ACA-8040-432E-B3A0-1E0440AB556A" target="_blank" rel="noopener noreferrer">collection</a>
|
||
<a href="https://docs.oracle.com/en/java/javase/12/gctuning/z-garbage-collector1.html#GUID-A5A42691-095E-47BA-B6DC-FB4E5FAA43D0" target="_blank" rel="noopener noreferrer">algorithms</a>
|
||
to choose from, each with different characteristics. The default algorithms (Parallel GC in Java
|
||
8, G1 in Java 9) freeze the JVM while collecting, while more recent algorithms
|
||
(<a href="https://wiki.openjdk.java.net/display/zgc" target="_blank" rel="noopener noreferrer">ZGC</a> and
|
||
<a href="https://wiki.openjdk.java.net/display/shenandoah" target="_blank" rel="noopener noreferrer">Shenandoah</a>) are designed to keep "stop the
|
||
world" to a minimum by doing collection work in parallel.</li>
|
||
</ul>
|
||
<p><strong>Allocation</strong>: Every language has a different way of interacting with "heap" memory, but the
|
||
principle is the same: running the allocator to allocate/deallocate memory takes time that can often
|
||
be put to better use. Understanding when your language interacts with the allocator is crucial, and
|
||
not always obvious. For example: C++ and Rust don't allocate heap memory for iterators, but Java
|
||
does (meaning potential GC pauses). Take time to understand heap behavior (I made a
|
||
<a href="https://speice.io/2019/02/understanding-allocations-in-rust">a guide for Rust</a>), and look into alternative
|
||
allocators (<a href="http://jemalloc.net/" target="_blank" rel="noopener noreferrer">jemalloc</a>,
|
||
<a href="https://gperftools.github.io/gperftools/tcmalloc.html" target="_blank" rel="noopener noreferrer">tcmalloc</a>) that might run faster than the
|
||
operating system default.</p>
|
||
<p><strong>Data Layout</strong>: How your data is arranged in memory matters;
|
||
<a href="https://www.youtube.com/watch?v=yy8jQgmhbAU" target="_blank" rel="noopener noreferrer">data-oriented design</a> and
|
||
<a href="https://www.youtube.com/watch?v=2EWejmkKlxs&feature=youtu.be&t=1185" target="_blank" rel="noopener noreferrer">cache locality</a> can have huge
|
||
impacts on performance. The C family of languages (C, value types in C#, C++) and Rust all have
|
||
guarantees about the shape every object takes in memory that others (e.g. Java and Python) can't
|
||
make. <a href="http://valgrind.org/docs/manual/cg-manual.html" target="_blank" rel="noopener noreferrer">Cachegrind</a> and kernel
|
||
<a href="https://perf.wiki.kernel.org/index.php/Main_Page" target="_blank" rel="noopener noreferrer">perf</a> counters are both great for understanding
|
||
how performance relates to memory layout.</p>
|
||
<p><strong>Just-In-Time Compilation</strong>: Languages that are compiled on the fly (LuaJIT, C#, Java, PyPy) are
|
||
great because they optimize your program for how it's actually being used, rather than how a
|
||
compiler expects it to be used. However, there's a variance problem if the program stops executing
|
||
while waiting for translation from VM bytecode to native code. As a remedy, many languages support
|
||
ahead-of-time compilation in addition to the JIT versions
|
||
(<a href="https://github.com/dotnet/corert" target="_blank" rel="noopener noreferrer">CoreRT</a> in C# and <a href="https://www.graalvm.org/" target="_blank" rel="noopener noreferrer">GraalVM</a> in Java).
|
||
On the other hand, LLVM supports
|
||
<a href="https://clang.llvm.org/docs/UsersManual.html#profile-guided-optimization" target="_blank" rel="noopener noreferrer">Profile Guided Optimization</a>,
|
||
which theoretically brings JIT benefits to non-JIT languages. Finally, be careful to avoid comparing
|
||
apples and oranges during benchmarks; you don't want your code to suddenly speed up because the JIT
|
||
compiler kicked in.</p>
|
||
<p><strong>Programming Tricks</strong>: These won't make or break performance, but can be useful in specific
|
||
circumstances. For example, C++ can use
|
||
<a href="https://www.youtube.com/watch?v=NH1Tta7purM&feature=youtu.be&t=1206" target="_blank" rel="noopener noreferrer">templates instead of branches</a>
|
||
in critical sections.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="kernel">Kernel<a href="https://speice.io/2019/06/high-performance-systems#kernel" class="hash-link" aria-label="Direct link to Kernel" title="Direct link to Kernel"></a></h2>
|
||
<p>Code you wrote is almost certainly not the <em>only</em> code running on your hardware. There are many ways
|
||
the operating system interacts with your program, from interrupts to system calls, that are
|
||
important to watch for. These are written from a Linux perspective, but Windows does typically have
|
||
equivalent functionality.</p>
|
||
<p><strong>Scheduling</strong>: The kernel is normally free to schedule any process on any core, so it's important
|
||
to reserve CPU cores exclusively for the important programs. There are a few parts to this: first,
|
||
limit the CPU cores that non-critical processes are allowed to run on by excluding cores from
|
||
scheduling
|
||
(<a href="https://www.linuxtopia.org/online_books/linux_kernel/kernel_configuration/re46.html" target="_blank" rel="noopener noreferrer"><code>isolcpus</code></a>
|
||
kernel command-line option), or by setting the <code>init</code> process CPU affinity
|
||
(<a href="https://access.redhat.com/solutions/2884991" target="_blank" rel="noopener noreferrer"><code>systemd</code> example</a>). Second, set critical processes
|
||
to run on the isolated cores by setting the
|
||
<a href="https://en.wikipedia.org/wiki/Processor_affinity" target="_blank" rel="noopener noreferrer">processor affinity</a> using
|
||
<a href="https://linux.die.net/man/1/taskset" target="_blank" rel="noopener noreferrer">taskset</a>. Finally, use
|
||
<a href="https://github.com/torvalds/linux/blob/master/Documentation/timers/NO_HZ.txt" target="_blank" rel="noopener noreferrer"><code>NO_HZ</code></a> or
|
||
<a href="https://linux.die.net/man/1/chrt" target="_blank" rel="noopener noreferrer"><code>chrt</code></a> to disable scheduling interrupts. Turning off
|
||
hyper-threading is also likely beneficial.</p>
|
||
<p><strong>System calls</strong>: Reading from a UNIX socket? Writing to a file? In addition to not knowing how long
|
||
the I/O operation takes, these all trigger expensive
|
||
<a href="https://en.wikipedia.org/wiki/System_call" target="_blank" rel="noopener noreferrer">system calls (syscalls)</a>. To handle these, the CPU must
|
||
<a href="https://en.wikipedia.org/wiki/Context_switch" target="_blank" rel="noopener noreferrer">context switch</a> to the kernel, let the kernel
|
||
operation complete, then context switch back to your program. We'd rather keep these
|
||
<a href="https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript" target="_blank" rel="noopener noreferrer">to a minimum</a> (see
|
||
timestamp 18:20). <a href="https://linux.die.net/man/1/strace" target="_blank" rel="noopener noreferrer">Strace</a> is your friend for understanding when
|
||
and where syscalls happen.</p>
|
||
<p><strong>Signal Handling</strong>: Far less likely to be an issue, but signals do trigger a context switch if your
|
||
code has a handler registered. This will be highly dependent on the application, but you can
|
||
<a href="https://www.linuxprogrammingblog.com/all-about-linux-signals?page=show#Blocking_signals" target="_blank" rel="noopener noreferrer">block signals</a>
|
||
if it's an issue.</p>
|
||
<p><strong>Interrupts</strong>: System interrupts are how devices connected to your computer notify the CPU that
|
||
something has happened. The CPU will then choose a processor core to pause and context switch to the
|
||
OS to handle the interrupt. Make sure that
|
||
<a href="http://www.alexonlinux.com/smp-affinity-and-proper-interrupt-handling-in-linux" target="_blank" rel="noopener noreferrer">SMP affinity</a> is
|
||
set so that interrupts are handled on a CPU core not running the program you care about.</p>
|
||
<p><strong><a href="https://www.kernel.org/doc/html/latest/vm/numa.html" target="_blank" rel="noopener noreferrer">NUMA</a></strong>: While NUMA is good at making
|
||
multi-cell systems transparent, there are variance implications; if the kernel moves a process
|
||
across nodes, future memory accesses must wait for the controller on the original node. Use
|
||
<a href="https://linux.die.net/man/8/numactl" target="_blank" rel="noopener noreferrer">numactl</a> to handle memory-/cpu-cell pinning so this doesn't
|
||
happen.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="hardware">Hardware<a href="https://speice.io/2019/06/high-performance-systems#hardware" class="hash-link" aria-label="Direct link to Hardware" title="Direct link to Hardware"></a></h2>
|
||
<p><strong>CPU Pipelining/Speculation</strong>: Speculative execution in modern processors gave us vulnerabilities
|
||
like Spectre, but it also gave us performance improvements like
|
||
<a href="https://stackoverflow.com/a/11227902/1454178" target="_blank" rel="noopener noreferrer">branch prediction</a>. And if the CPU mis-speculates
|
||
your code, there's variance associated with rewind and replay. While the compiler knows a lot about
|
||
how your CPU <a href="https://youtu.be/nAbCKa0FzjQ?t=4467" target="_blank" rel="noopener noreferrer">pipelines instructions</a>, code can be
|
||
<a href="https://www.youtube.com/watch?v=NH1Tta7purM&feature=youtu.be&t=755" target="_blank" rel="noopener noreferrer">structured to help</a> the branch
|
||
predictor.</p>
|
||
<p><strong>Paging</strong>: For most systems, virtual memory is incredible. Applications live in their own worlds,
|
||
and the CPU/<a href="https://en.wikipedia.org/wiki/Memory_management_unit" target="_blank" rel="noopener noreferrer">MMU</a> figures out the details.
|
||
However, there's a variance penalty associated with memory paging and caching; if you access more
|
||
memory pages than the <a href="https://en.wikipedia.org/wiki/Translation_lookaside_buffer" target="_blank" rel="noopener noreferrer">TLB</a> can store,
|
||
you'll have to wait for the page walk. Kernel perf tools are necessary to figure out if this is an
|
||
issue, but using <a href="https://blog.pythian.com/performance-tuning-hugepages-in-linux/" target="_blank" rel="noopener noreferrer">huge pages</a> can
|
||
reduce TLB burdens. Alternately, running applications in a hypervisor like
|
||
<a href="https://github.com/siemens/jailhouse" target="_blank" rel="noopener noreferrer">Jailhouse</a> allows one to skip virtual memory entirely, but
|
||
this is probably more work than the benefits are worth.</p>
|
||
<p><strong>Network Interfaces</strong>: When more than one computer is involved, variance can go up dramatically.
|
||
Tuning kernel
|
||
<a href="https://github.com/leandromoreira/linux-network-performance-parameters" target="_blank" rel="noopener noreferrer">network parameters</a> may be
|
||
helpful, but modern systems more frequently opt to skip the kernel altogether with a technique
|
||
called <a href="https://blog.cloudflare.com/kernel-bypass/" target="_blank" rel="noopener noreferrer">kernel bypass</a>. This typically requires
|
||
specialized hardware and <a href="https://www.openonload.org/" target="_blank" rel="noopener noreferrer">drivers</a>, but even industries like
|
||
<a href="https://www.bbc.co.uk/rd/blog/2018-04-high-speed-networking-open-source-kernel-bypass" target="_blank" rel="noopener noreferrer">telecom</a> are
|
||
finding the benefits.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="networks">Networks<a href="https://speice.io/2019/06/high-performance-systems#networks" class="hash-link" aria-label="Direct link to Networks" title="Direct link to Networks"></a></h2>
|
||
<p><strong>Routing</strong>: There's a reason financial firms are willing to pay
|
||
<a href="https://sniperinmahwah.wordpress.com/2019/03/26/4-les-moeres-english-version/" target="_blank" rel="noopener noreferrer">millions of euros</a>
|
||
for rights to a small plot of land - having a straight-line connection from point A to point B means
|
||
the path their data takes is the shortest possible. In contrast, there are currently 6 computers in
|
||
between me and Google, but that may change at any moment if my ISP realizes a
|
||
<a href="https://en.wikipedia.org/wiki/Border_Gateway_Protocol" target="_blank" rel="noopener noreferrer">more efficient route</a> is available. Whether
|
||
it's using
|
||
<a href="https://sniperinmahwah.wordpress.com/2018/05/07/shortwave-trading-part-i-the-west-chicago-tower-mystery/" target="_blank" rel="noopener noreferrer">research-quality equipment</a>
|
||
for shortwave radio, or just making sure there's no data inadvertently going between data centers,
|
||
routing matters.</p>
|
||
<p><strong>Protocol</strong>: TCP as a network protocol is awesome: guaranteed and in-order delivery, flow control,
|
||
and congestion control all built in. But these attributes make the most sense when networking
|
||
infrastructure is lossy; for systems that expect nearly all packets to be delivered correctly, the
|
||
setup handshaking and packet acknowledgment are just overhead. Using UDP (unicast or multicast) may
|
||
make sense in these contexts as it avoids the chatter needed to track connection state, and
|
||
<a href="https://iextrading.com/docs/IEX%20Transport%20Specification.pdf" target="_blank" rel="noopener noreferrer">gap-fill</a>
|
||
<a href="http://www.nasdaqtrader.com/content/technicalsupport/specifications/dataproducts/moldudp64.pdf" target="_blank" rel="noopener noreferrer">strategies</a>
|
||
can handle the rest.</p>
|
||
<p><strong>Switching</strong>: Many routers/switches handle packets using "store-and-forward" behavior: wait for the
|
||
whole packet, validate checksums, and then send to the next device. In variance terms, the time
|
||
needed to move data between two nodes is proportional to the size of that data; the switch must
|
||
"store" all data before it can calculate checksums and "forward" to the next node. With
|
||
<a href="https://www.networkworld.com/article/2241573/latency-and-jitter--cut-through-design-pays-off-for-arista--blade.html" target="_blank" rel="noopener noreferrer">"cut-through"</a>
|
||
designs, switches will begin forwarding data as soon as they know where the destination is,
|
||
checksums be damned. This means there's a fixed cost (at the switch) for network traffic, no matter
|
||
the size.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="final-thoughts">Final Thoughts<a href="https://speice.io/2019/06/high-performance-systems#final-thoughts" class="hash-link" aria-label="Direct link to Final Thoughts" title="Direct link to Final Thoughts"></a></h2>
|
||
<p>High-performance systems, regardless of industry, are not magical. They do require extreme precision
|
||
and attention to detail, but they're designed, built, and operated by regular people, using a lot of
|
||
tools that are publicly available. Interested in seeing how context switching affects performance of
|
||
your benchmarks? <code>taskset</code> should be installed in all modern Linux distributions, and can be used to
|
||
make sure the OS never migrates your process. Curious how often garbage collection triggers during a
|
||
crucial operation? Your language of choice will typically expose details of its operations
|
||
(<a href="https://docs.python.org/3/library/gc.html" target="_blank" rel="noopener noreferrer">Python</a>,
|
||
<a href="https://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#DebuggingOptions" target="_blank" rel="noopener noreferrer">Java</a>).
|
||
Want to know how hard your program is stressing the TLB? Use <code>perf record</code> and look for
|
||
<code>dtlb_load_misses.miss_causes_a_walk</code>.</p>
|
||
<p>Two final guiding questions, then: first, before attempting to apply some of the technology above to
|
||
your own systems, can you first identify
|
||
<a href="http://wiki.c2.com/?PrematureOptimization" target="_blank" rel="noopener noreferrer">where/when you care</a> about "high-performance"? As an
|
||
example, if parts of a system rely on humans pushing buttons, CPU pinning won't have any measurable
|
||
effect. Humans are already far too slow to react in time. Second, if you're using benchmarks, are
|
||
they being designed in a way that's actually helpful? Tools like
|
||
<a href="http://www.serpentine.com/criterion/" target="_blank" rel="noopener noreferrer">Criterion</a> (also in
|
||
<a href="https://github.com/bheisler/criterion.rs" target="_blank" rel="noopener noreferrer">Rust</a>) and Google's
|
||
<a href="https://github.com/google/benchmark" target="_blank" rel="noopener noreferrer">Benchmark</a> output not only average run time, but variance as
|
||
well; your benchmarking environment is subject to the same concerns your production environment is.</p>
|
||
<p>Finally, I believe high-performance systems are a matter of philosophy, not necessarily technique.
|
||
Rigorous focus on variance is the first step, and there are plenty of ways to measure and mitigate
|
||
it; once that's at an acceptable level, then optimize for speed.</p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[Making bread]]></title>
|
||
<link>https://speice.io/2019/05/making-bread</link>
|
||
<guid>https://speice.io/2019/05/making-bread</guid>
|
||
<pubDate>Fri, 03 May 2019 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[Having recently started my "gardening leave" between positions, I have some more personal time]]></description>
|
||
<content:encoded><![CDATA[<p>Having recently started my "gardening leave" between positions, I have some more personal time
|
||
available. I'm planning to stay productive, contributing to some open-source projects, but it also
|
||
occurred to me that despite <a href="https://speice.io/2018/05/hello.html" target="_blank" rel="noopener noreferrer">talking about</a> bread pics, this
|
||
blog has been purely technical. Maybe I'll change the site title from "The Old Speice Guy" to "Bites
|
||
and Bytes"?</p>
|
||
<p>Either way, I'm baking a little bit again, and figured it was worth taking a quick break to focus on
|
||
some lighter material. I recently learned two critically important lessons: first, the temperature
|
||
of the dough when you put the yeast in makes a huge difference.</p>
|
||
<p>Previously, when I wasn't paying attention to dough temperature:</p>
|
||
<p><img decoding="async" loading="lazy" alt="Whole weat dough" src="https://speice.io/assets/images/whole-wheat-not-rising-922d19641c91922b7634fff1d6f15e6d.jpg" width="432" height="549" class="img_ev3q"></p>
|
||
<p>Compared with what happens when I put the dough in the microwave for a defrost cycle because the
|
||
water I used wasn't warm enough:</p>
|
||
<p><img decoding="async" loading="lazy" alt="White dough" src="https://speice.io/assets/images/white-dough-rising-before-fold-c5a4424f9a5227f1f8e86b13b436782c.jpg" width="432" height="438" class="img_ev3q"></p>
|
||
<p>I mean, just look at the bubbles!</p>
|
||
<p><img decoding="async" loading="lazy" alt="White dough with bubbles" src="https://speice.io/assets/images/white-dough-rising-after-fold-d7a27f12c1d2be572807105d6d7321f3.jpg" width="432" height="428" class="img_ev3q"></p>
|
||
<p>After shaping the dough, I've got two loaves ready:</p>
|
||
<p><img decoding="async" loading="lazy" alt="Shaped loaves" src="https://speice.io/assets/images/shaped-loaves-cea15e9ccef6b180525abaee2d288880.jpg" width="864" height="486" class="img_ev3q"></p>
|
||
<p>Now, the recipe normally calls for a Dutch Oven to bake the bread because it keeps the dough from
|
||
drying out in the oven. Because I don't own a Dutch Oven, I typically put a casserole dish on the
|
||
bottom rack and fill it with water so there's still some moisture in the oven. This time, I forgot
|
||
to add the water and learned my second lesson: never add room-temperature water to a glass dish
|
||
that's currently at 500 degrees.</p>
|
||
<p><img decoding="async" loading="lazy" alt="Shattered glass dish" src="https://speice.io/assets/images/shattered-glass-0b56af0302f7a8c3295bf43cbab77ffe.jpg" width="864" height="486" class="img_ev3q"></p>
|
||
<p>Needless to say, trying to pull out sharp glass from an incredibly hot oven is not what I expected
|
||
to be doing during my garden leave.</p>
|
||
<p>In the end, the bread crust wasn't great, but the bread itself turned out pretty alright:</p>
|
||
<p><img decoding="async" loading="lazy" alt="Baked bread" src="https://speice.io/assets/images/final-product-607f96e84dada915fa422a7e5d524ca1.jpg" width="864" height="486" class="img_ev3q"></p>
|
||
<p>I've been writing a lot more during this break, so I'm looking forward to sharing that in the
|
||
future. In the mean-time, I'm planning on making a sandwich.</p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[Allocations in Rust: Summary]]></title>
|
||
<link>https://speice.io/2019/02/summary</link>
|
||
<guid>https://speice.io/2019/02/summary</guid>
|
||
<pubDate>Sat, 09 Feb 2019 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[While there's a lot of interesting detail captured in this series, it's often helpful to have a]]></description>
|
||
<content:encoded><![CDATA[<p>While there's a lot of interesting detail captured in this series, it's often helpful to have a
|
||
document that answers some "yes/no" questions. You may not care about what an <code>Iterator</code> looks like
|
||
in assembly, you just need to know whether it allocates an object on the heap or not. And while Rust
|
||
will prioritize the fastest behavior it can, here are the rules for each memory type:</p>
|
||
<p><strong>Global Allocation</strong>:</p>
|
||
<ul>
|
||
<li><code>const</code> is a fixed value; the compiler is allowed to copy it wherever useful.</li>
|
||
<li><code>static</code> is a fixed reference; the compiler will guarantee it is unique.</li>
|
||
</ul>
|
||
<p><strong>Stack Allocation</strong>:</p>
|
||
<ul>
|
||
<li>Everything not using a smart pointer will be allocated on the stack.</li>
|
||
<li>Structs, enums, iterators, arrays, and closures are all stack allocated.</li>
|
||
<li>Cell types (<code>RefCell</code>) behave like smart pointers, but are stack-allocated.</li>
|
||
<li>Inlining (<code>#[inline]</code>) will not affect allocation behavior for better or worse.</li>
|
||
<li>Types that are marked <code>Copy</code> are guaranteed to have their contents stack-allocated.</li>
|
||
</ul>
|
||
<p><strong>Heap Allocation</strong>:</p>
|
||
<ul>
|
||
<li>Smart pointers (<code>Box</code>, <code>Rc</code>, <code>Mutex</code>, etc.) allocate their contents in heap memory.</li>
|
||
<li>Collections (<code>HashMap</code>, <code>Vec</code>, <code>String</code>, etc.) allocate their contents in heap memory.</li>
|
||
<li>Some smart pointers in the standard library have counterparts in other crates that don't need heap
|
||
memory. If possible, use those.</li>
|
||
</ul>
|
||
<p><img decoding="async" loading="lazy" alt="Container Sizes in Rust" src="https://speice.io/assets/images/container-size-7fd54cbb2391e3e7310b0424c5f92cc1.svg" width="960" height="540" class="img_ev3q"></p>
|
||
<p>-- <a href="https://docs.google.com/presentation/d/1q-c7UAyrUlM-eZyTo1pd8SZ0qwA_wYxmPZVOQkoDmH4/edit?usp=sharing" target="_blank" rel="noopener noreferrer">Raph Levien</a></p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[Allocations in Rust: Compiler optimizations]]></title>
|
||
<link>https://speice.io/2019/02/08/compiler-optimizations</link>
|
||
<guid>https://speice.io/2019/02/08/compiler-optimizations</guid>
|
||
<pubDate>Fri, 08 Feb 2019 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[A lot. The answer is a lot.]]></description>
|
||
<content:encoded><![CDATA[<p>Up to this point, we've been discussing memory usage in the Rust language by focusing on simple
|
||
rules that are mostly right for small chunks of code. We've spent time showing how those rules work
|
||
themselves out in practice, and become familiar with reading the assembly code needed to see each
|
||
memory type (global, stack, heap) in action.</p>
|
||
<p>Throughout the series so far, we've put a handicap on the code. In the name of consistent and
|
||
understandable results, we've asked the compiler to pretty please leave the training wheels on. Now
|
||
is the time where we throw out all the rules and take off the kid gloves. As it turns out, both the
|
||
Rust compiler and the LLVM optimizers are incredibly sophisticated, and we'll step back and let them
|
||
do their job.</p>
|
||
<p>Similar to
|
||
<a href="https://www.youtube.com/watch?v=bSkpMdDe4g4" target="_blank" rel="noopener noreferrer">"What Has My Compiler Done For Me Lately?"</a>, we're
|
||
focusing on interesting things the Rust language (and LLVM!) can do with memory management. We'll
|
||
still be looking at assembly code to understand what's going on, but it's important to mention
|
||
again: <strong>please use automated tools like <a href="https://crates.io/crates/alloc_counter" target="_blank" rel="noopener noreferrer">alloc-counter</a> to
|
||
double-check memory behavior if it's something you care about</strong>. It's far too easy to mis-read
|
||
assembly in large code sections, you should always verify behavior if you care about memory usage.</p>
|
||
<p>The guiding principal as we move forward is this: <em>optimizing compilers won't produce worse programs
|
||
than we started with.</em> There won't be any situations where stack allocations get moved to heap
|
||
allocations. There will, however, be an opera of optimization.</p>
|
||
<p><strong>Update 2019-02-10</strong>: When debugging a
|
||
<a href="https://gitlab.com/sio4/code/alloc-counter/issues/1" target="_blank" rel="noopener noreferrer">related issue</a>, it was discovered that the
|
||
original code worked because LLVM optimized out the entire function, rather than just the allocation
|
||
segments. The code has been updated with proper use of
|
||
<a href="https://doc.rust-lang.org/std/ptr/fn.read_volatile.html" target="_blank" rel="noopener noreferrer"><code>read_volatile</code></a>, and a previous section
|
||
on vector capacity has been removed.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-case-of-the-disappearing-box">The Case of the Disappearing Box<a href="https://speice.io/2019/02/08/compiler-optimizations#the-case-of-the-disappearing-box" class="hash-link" aria-label="Direct link to The Case of the Disappearing Box" title="Direct link to The Case of the Disappearing Box"></a></h2>
|
||
<p>Our first optimization comes when LLVM can reason that the lifetime of an object is sufficiently
|
||
short that heap allocations aren't necessary. In these cases, LLVM will move the allocation to the
|
||
stack instead! The way this interacts with <code>#[inline]</code> attributes is a bit opaque, but the important
|
||
part is that LLVM can sometimes do better than the baseline Rust language:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">alloc</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">GlobalAlloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">System</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">sync</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">atomic</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">AtomicBool</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ordering</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">cmp</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Turn on panicking if we allocate on the heap</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">DO_PANIC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">store</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token boolean" style="color:hsl(35, 99%, 36%)">true</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ordering</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">SeqCst</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// The compiler is able to see through the constant `Box`</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// and directly compare `x` to 24 - assembly line 73</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Box</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">24</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> equals </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">==</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// This call to drop is eliminated</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">drop</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Need to mark the comparison result as volatile so that</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// LLVM doesn't strip out all the code. If `y` is marked</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// volatile instead, allocation will be forced.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">unsafe</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">ptr</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">read_volatile</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">equals</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Turn off panicking, as there are some deallocations</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// when we exit main.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">DO_PANIC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">store</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token boolean" style="color:hsl(35, 99%, 36%)">false</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ordering</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">SeqCst</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">cmp</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">12</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[global_allocator]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">A</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">PanicAllocator</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">PanicAllocator</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">DO_PANIC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">AtomicBool</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">AtomicBool</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token boolean" style="color:hsl(35, 99%, 36%)">false</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">PanicAllocator</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">unsafe</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">impl</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">GlobalAlloc</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">for</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">PanicAllocator</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">unsafe</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">alloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">if</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">DO_PANIC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">load</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ordering</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">SeqCst</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">panic!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"Unexpected allocation."</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">System</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">alloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">unsafe</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">dealloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> ptr</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">if</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">DO_PANIC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">load</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ordering</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">SeqCst</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">panic!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"Unexpected deallocation."</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">System</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">dealloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">ptr</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/BZ_Yp3" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
<p>-- <a href="https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=4a765f753183d5b919f62c71d2109d5d" target="_blank" rel="noopener noreferrer">Rust Playground</a></p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="dr-array-or-how-i-learned-to-love-the-optimizer">Dr. Array or: how I learned to love the optimizer<a href="https://speice.io/2019/02/08/compiler-optimizations#dr-array-or-how-i-learned-to-love-the-optimizer" class="hash-link" aria-label="Direct link to Dr. Array or: how I learned to love the optimizer" title="Direct link to Dr. Array or: how I learned to love the optimizer"></a></h2>
|
||
<p>Finally, this isn't so much about LLVM figuring out different memory behavior, but LLVM stripping
|
||
out code that doesn't do anything. Optimizations of this type have a lot of nuance to them; if
|
||
you're not careful, they can make your benchmarks look
|
||
<a href="https://www.youtube.com/watch?v=nXaxk27zwlk&feature=youtu.be&t=1199" target="_blank" rel="noopener noreferrer">impossibly good</a>. In Rust, the
|
||
<code>black_box</code> function (implemented in both
|
||
<a href="https://doc.rust-lang.org/1.1.0/test/fn.black_box.html" target="_blank" rel="noopener noreferrer"><code>libtest</code></a> and
|
||
<a href="https://docs.rs/criterion/0.2.10/criterion/fn.black_box.html" target="_blank" rel="noopener noreferrer"><code>criterion</code></a>) will tell the compiler
|
||
to disable this kind of optimization. But if you let LLVM remove unnecessary code, you can end up
|
||
running programs that previously caused errors:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[derive(Default)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">TwoFiftySix</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> _a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u64</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[derive(Default)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">EightK</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> _a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">TwoFiftySix</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[derive(Default)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">TwoFiftySixK</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> _a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">EightK</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[derive(Default)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">EightM</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> _a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">TwoFiftySixK</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Normally this blows up because we can't reserve size on stack</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// for the `EightM` struct. But because the compiler notices we</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// never do anything with `_x`, it optimizes out the stack storage</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// and the program completes successfully.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> _x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">EightM</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">default</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/daHn7P" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
<p>-- <a href="https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=4c253bf26072119896ab93c6ef064dc0" target="_blank" rel="noopener noreferrer">Rust Playground</a></p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[Allocations in Rust: Dynamic memory]]></title>
|
||
<link>https://speice.io/2019/02/a-heaping-helping</link>
|
||
<guid>https://speice.io/2019/02/a-heaping-helping</guid>
|
||
<pubDate>Thu, 07 Feb 2019 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and]]></description>
|
||
<content:encoded><![CDATA[<p>Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and
|
||
some languages go to extreme lengths to protect users from themselves (Java, Python). In Rust, how
|
||
the language uses dynamic memory (also referred to as the <strong>heap</strong>) is a system called <em>ownership</em>.
|
||
And as the docs mention, ownership
|
||
<a href="https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html" target="_blank" rel="noopener noreferrer">is Rust's most unique feature</a>.</p>
|
||
<p>The heap is used in two situations; when the compiler is unable to predict either the <em>total size of
|
||
memory needed</em>, or <em>how long the memory is needed for</em>, it allocates space in the heap.</p>
|
||
<p>This happens
|
||
pretty frequently; if you want to download the Google home page, you won't know how large it is
|
||
until your program runs. And when you're finished with Google, we deallocate the memory so it can be
|
||
used to store other webpages. If you're interested in a slightly longer explanation of the heap,
|
||
check out
|
||
<a href="https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html#the-stack-and-the-heap" target="_blank" rel="noopener noreferrer">The Stack and the Heap</a>
|
||
in Rust's documentation.</p>
|
||
<p>We won't go into detail on how the heap is managed; the
|
||
<a href="https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html" target="_blank" rel="noopener noreferrer">ownership documentation</a> does a
|
||
phenomenal job explaining both the "why" and "how" of memory management. Instead, we're going to
|
||
focus on understanding "when" heap allocations occur in Rust.</p>
|
||
<p>To start off, take a guess for how many allocations happen in the program below:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>It's obviously a trick question; while no heap allocations occur as a result of that code, the setup
|
||
needed to call <code>main</code> does allocate on the heap. Here's a way to show it:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#![feature(integer_atomics)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">alloc</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">GlobalAlloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">System</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">sync</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">atomic</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">AtomicU64</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ordering</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">ALLOCATION_COUNT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">AtomicU64</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">AtomicU64</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">CountingAllocator</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">unsafe</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">impl</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">GlobalAlloc</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">for</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">CountingAllocator</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">unsafe</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">alloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">ALLOCATION_COUNT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">fetch_add</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ordering</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">SeqCst</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">System</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">alloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">unsafe</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">dealloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> ptr</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">System</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">dealloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">ptr</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[global_allocator]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">A</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">CountingAllocator</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">CountingAllocator</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">ALLOCATION_COUNT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">fetch_add</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ordering</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">SeqCst</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">println!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"There were {} allocations before calling main!"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>--
|
||
<a href="https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=fb5060025ba79fc0f906b65a4ef8eb8e" target="_blank" rel="noopener noreferrer">Rust Playground</a></p>
|
||
<p>As of the time of writing, there are five allocations that happen before <code>main</code> is ever called.</p>
|
||
<p>But when we want to understand more practically where heap allocation happens, we'll follow this
|
||
guide:</p>
|
||
<ul>
|
||
<li>Smart pointers hold their contents in the heap</li>
|
||
<li>Collections are smart pointers for many objects at a time, and reallocate when they need to grow</li>
|
||
</ul>
|
||
<p>Finally, there are two "addendum" issues that are important to address when discussing Rust and the
|
||
heap:</p>
|
||
<ul>
|
||
<li>Non-heap alternatives to many standard library types are available.</li>
|
||
<li>Special allocators to track memory behavior should be used to benchmark code.</li>
|
||
</ul>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="smart-pointers">Smart pointers<a href="https://speice.io/2019/02/a-heaping-helping#smart-pointers" class="hash-link" aria-label="Direct link to Smart pointers" title="Direct link to Smart pointers"></a></h2>
|
||
<p>The first thing to note are the "smart pointer" types. When you have data that must outlive the
|
||
scope in which it is declared, or your data is of unknown or dynamic size, you'll make use of these
|
||
types.</p>
|
||
<p>The term <a href="https://en.wikipedia.org/wiki/Smart_pointer" target="_blank" rel="noopener noreferrer">smart pointer</a> comes from C++, and while it's
|
||
closely linked to a general design pattern of
|
||
<a href="https://en.cppreference.com/w/cpp/language/raii" target="_blank" rel="noopener noreferrer">"Resource Acquisition Is Initialization"</a>, we'll
|
||
use it here specifically to describe objects that are responsible for managing ownership of data
|
||
allocated on the heap. The smart pointers available in the <code>alloc</code> crate should look mostly
|
||
familiar:</p>
|
||
<ul>
|
||
<li><a href="https://doc.rust-lang.org/alloc/boxed/struct.Box.html" target="_blank" rel="noopener noreferrer"><code>Box</code></a></li>
|
||
<li><a href="https://doc.rust-lang.org/alloc/rc/struct.Rc.html" target="_blank" rel="noopener noreferrer"><code>Rc</code></a></li>
|
||
<li><a href="https://doc.rust-lang.org/alloc/sync/struct.Arc.html" target="_blank" rel="noopener noreferrer"><code>Arc</code></a></li>
|
||
<li><a href="https://doc.rust-lang.org/alloc/borrow/enum.Cow.html" target="_blank" rel="noopener noreferrer"><code>Cow</code></a></li>
|
||
</ul>
|
||
<p>The <a href="https://doc.rust-lang.org/std/" target="_blank" rel="noopener noreferrer">standard library</a> also defines some smart pointers to manage
|
||
heap objects, though more than can be covered here. Some examples are:</p>
|
||
<ul>
|
||
<li><a href="https://doc.rust-lang.org/std/sync/struct.RwLock.html" target="_blank" rel="noopener noreferrer"><code>RwLock</code></a></li>
|
||
<li><a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html" target="_blank" rel="noopener noreferrer"><code>Mutex</code></a></li>
|
||
</ul>
|
||
<p>Finally, there is one <a href="https://www.merriam-webster.com/dictionary/gotcha" target="_blank" rel="noopener noreferrer">"gotcha"</a>: <strong>cell types</strong>
|
||
(like <a href="https://doc.rust-lang.org/stable/core/cell/struct.RefCell.html" target="_blank" rel="noopener noreferrer"><code>RefCell</code></a>) look and behave
|
||
similarly, but <strong>don't involve heap allocation</strong>. The
|
||
<a href="https://doc.rust-lang.org/stable/core/cell/index.html" target="_blank" rel="noopener noreferrer"><code>core::cell</code> docs</a> have more information.</p>
|
||
<p>When a smart pointer is created, the data it is given is placed in heap memory and the location of
|
||
that data is recorded in the smart pointer. Once the smart pointer has determined it's safe to
|
||
deallocate that memory (when a <code>Box</code> has
|
||
<a href="https://doc.rust-lang.org/stable/std/boxed/index.html" target="_blank" rel="noopener noreferrer">gone out of scope</a> or a reference count
|
||
<a href="https://doc.rust-lang.org/alloc/rc/index.html" target="_blank" rel="noopener noreferrer">goes to zero</a>), the heap space is reclaimed. We can
|
||
prove these types use heap memory by looking at code:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">rc</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Rc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">sync</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Arc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">borrow</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Cow</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">my_box</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Drop at assembly line 1640</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Box</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">my_rc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Drop at assembly line 1650</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Rc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">my_arc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Drop at assembly line 1660</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Arc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">my_cow</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Drop at assembly line 1672</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Cow</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">from</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"drop"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/4AMQug" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="collections">Collections<a href="https://speice.io/2019/02/a-heaping-helping#collections" class="hash-link" aria-label="Direct link to Collections" title="Direct link to Collections"></a></h2>
|
||
<p>Collection types use heap memory because their contents have dynamic size; they will request more
|
||
memory <a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.reserve" target="_blank" rel="noopener noreferrer">when needed</a>, and can
|
||
<a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.shrink_to_fit" target="_blank" rel="noopener noreferrer">release memory</a> when it's
|
||
no longer necessary. This dynamic property forces Rust to heap allocate everything they contain. In
|
||
a way, <strong>collections are smart pointers for many objects at a time</strong>. Common types that fall under
|
||
this umbrella are <a href="https://doc.rust-lang.org/stable/alloc/vec/struct.Vec.html" target="_blank" rel="noopener noreferrer"><code>Vec</code></a>,
|
||
<a href="https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html" target="_blank" rel="noopener noreferrer"><code>HashMap</code></a>, and
|
||
<a href="https://doc.rust-lang.org/stable/alloc/string/struct.String.html" target="_blank" rel="noopener noreferrer"><code>String</code></a> (not
|
||
<a href="https://doc.rust-lang.org/std/primitive.str.html" target="_blank" rel="noopener noreferrer"><code>str</code></a>).</p>
|
||
<p>While collections store the objects they own in heap memory, <em>creating new collections will not
|
||
allocate on the heap</em>. This is a bit weird; if we call <code>Vec::new()</code>, the assembly shows a
|
||
corresponding call to <code>real_drop_in_place</code>:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">my_vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Drop in place at line 481</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/1WkNtC" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
<p>But because the vector has no elements to manage, no calls to the allocator will ever be dispatched:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">alloc</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">GlobalAlloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">System</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">sync</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">atomic</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">AtomicBool</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ordering</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Turn on panicking if we allocate on the heap</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">DO_PANIC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">store</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token boolean" style="color:hsl(35, 99%, 36%)">true</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ordering</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">SeqCst</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Interesting bit happens here</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">drop</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Turn panicking back off, some deallocations occur</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// after main as well.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">DO_PANIC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">store</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token boolean" style="color:hsl(35, 99%, 36%)">false</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ordering</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">SeqCst</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[global_allocator]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">A</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">PanicAllocator</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">PanicAllocator</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">DO_PANIC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">AtomicBool</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">AtomicBool</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token boolean" style="color:hsl(35, 99%, 36%)">false</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">PanicAllocator</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">unsafe</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">impl</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">GlobalAlloc</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">for</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">PanicAllocator</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">unsafe</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">alloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">if</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">DO_PANIC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">load</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ordering</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">SeqCst</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">panic!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"Unexpected allocation."</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">System</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">alloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">unsafe</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">dealloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> ptr</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">if</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">DO_PANIC</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">load</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ordering</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">SeqCst</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">panic!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"Unexpected deallocation."</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">System</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">dealloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">ptr</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> layout</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>--
|
||
<a href="https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=831a297d176d015b1f9ace01ae416cc6" target="_blank" rel="noopener noreferrer">Rust Playground</a></p>
|
||
<p>Other standard library types follow the same behavior; make sure to check out
|
||
<a href="https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.new" target="_blank" rel="noopener noreferrer"><code>HashMap::new()</code></a>,
|
||
and <a href="https://doc.rust-lang.org/std/string/struct.String.html#method.new" target="_blank" rel="noopener noreferrer"><code>String::new()</code></a>.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="heap-alternatives">Heap Alternatives<a href="https://speice.io/2019/02/a-heaping-helping#heap-alternatives" class="hash-link" aria-label="Direct link to Heap Alternatives" title="Direct link to Heap Alternatives"></a></h2>
|
||
<p>While it is a bit strange to speak of the stack after spending time with the heap, it's worth
|
||
pointing out that some heap-allocated objects in Rust have stack-based counterparts provided by
|
||
other crates. If you have need of the functionality, but want to avoid allocating, there are
|
||
typically alternatives available.</p>
|
||
<p>When it comes to some standard library smart pointers
|
||
(<a href="https://doc.rust-lang.org/std/sync/struct.RwLock.html" target="_blank" rel="noopener noreferrer"><code>RwLock</code></a> and
|
||
<a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html" target="_blank" rel="noopener noreferrer"><code>Mutex</code></a>), stack-based alternatives are
|
||
provided in crates like <a href="https://crates.io/crates/parking_lot" target="_blank" rel="noopener noreferrer">parking_lot</a> and
|
||
<a href="https://crates.io/crates/spin" target="_blank" rel="noopener noreferrer">spin</a>. You can check out
|
||
<a href="https://docs.rs/lock_api/0.1.5/lock_api/struct.RwLock.html" target="_blank" rel="noopener noreferrer"><code>lock_api::RwLock</code></a>,
|
||
<a href="https://docs.rs/lock_api/0.1.5/lock_api/struct.Mutex.html" target="_blank" rel="noopener noreferrer"><code>lock_api::Mutex</code></a>, and
|
||
<a href="https://mvdnes.github.io/rust-docs/spin-rs/spin/struct.Once.html" target="_blank" rel="noopener noreferrer"><code>spin::Once</code></a> if you're in need
|
||
of synchronization primitives.</p>
|
||
<p><a href="https://crates.io/crates/thread-id" target="_blank" rel="noopener noreferrer">thread_id</a> may be necessary if you're implementing an allocator
|
||
because <a href="https://doc.rust-lang.org/std/thread/struct.ThreadId.html" target="_blank" rel="noopener noreferrer"><code>thread::current().id()</code></a> uses a
|
||
<a href="https://doc.rust-lang.org/stable/src/std/sys_common/thread_info.rs.html#17-36" target="_blank" rel="noopener noreferrer"><code>thread_local!</code> structure</a>
|
||
that needs heap allocation.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="tracing-allocators">Tracing Allocators<a href="https://speice.io/2019/02/a-heaping-helping#tracing-allocators" class="hash-link" aria-label="Direct link to Tracing Allocators" title="Direct link to Tracing Allocators"></a></h2>
|
||
<p>When writing performance-sensitive code, there's no alternative to measuring your code. If you
|
||
didn't write a benchmark,
|
||
<a href="https://www.youtube.com/watch?v=2EWejmkKlxs&feature=youtu.be&t=263" target="_blank" rel="noopener noreferrer">you don't care about it's performance</a>
|
||
You should never rely on your instincts when
|
||
<a href="https://www.youtube.com/watch?v=NH1Tta7purM" target="_blank" rel="noopener noreferrer">a microsecond is an eternity</a>.</p>
|
||
<p>Similarly, there's great work going on in Rust with allocators that keep track of what they're doing
|
||
(like <a href="https://crates.io/crates/alloc_counter" target="_blank" rel="noopener noreferrer"><code>alloc_counter</code></a>). When it comes to tracking heap
|
||
behavior, it's easy to make mistakes; please write tests and make sure you have tools to guard
|
||
against future issues.</p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[Allocations in Rust: Fixed memory]]></title>
|
||
<link>https://speice.io/2019/02/stacking-up</link>
|
||
<guid>https://speice.io/2019/02/stacking-up</guid>
|
||
<pubDate>Wed, 06 Feb 2019 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[const and static are perfectly fine, but it's relatively rare that we know at compile-time about]]></description>
|
||
<content:encoded><![CDATA[<p><code>const</code> and <code>static</code> are perfectly fine, but it's relatively rare that we know at compile-time about
|
||
either values or references that will be the same for the duration of our program. Put another way,
|
||
it's not often the case that either you or your compiler knows how much memory your entire program
|
||
will ever need.</p>
|
||
<p>However, there are still some optimizations the compiler can do if it knows how much memory
|
||
individual functions will need. Specifically, the compiler can make use of "stack" memory (as
|
||
opposed to "heap" memory) which can be managed far faster in both the short- and long-term.</p>
|
||
<p>When requesting memory, the <a href="http://www.cs.virginia.edu/~evans/cs216/guides/x86.html" target="_blank" rel="noopener noreferrer"><code>push</code> instruction</a>
|
||
can typically complete in <a href="https://agner.org/optimize/instruction_tables.ods" target="_blank" rel="noopener noreferrer">1 or 2 cycles</a> (<1ns
|
||
on modern CPUs). Contrast that to heap memory which requires an allocator (specialized
|
||
software to track what memory is in use) to reserve space. When you're finished with stack memory,
|
||
the <code>pop</code> instruction runs in 1-3 cycles, as opposed to an allocator needing to worry about memory
|
||
fragmentation and other issues with the heap. All sorts of incredibly sophisticated techniques have
|
||
been used to design allocators:</p>
|
||
<ul>
|
||
<li><a href="https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)" target="_blank" rel="noopener noreferrer">Garbage Collection</a>
|
||
strategies like <a href="https://en.wikipedia.org/wiki/Tracing_garbage_collection" target="_blank" rel="noopener noreferrer">Tracing</a> (used in
|
||
<a href="https://www.oracle.com/technetwork/java/javase/tech/g1-intro-jsp-135488.html" target="_blank" rel="noopener noreferrer">Java</a>) and
|
||
<a href="https://en.wikipedia.org/wiki/Reference_counting" target="_blank" rel="noopener noreferrer">Reference counting</a> (used in
|
||
<a href="https://docs.python.org/3/extending/extending.html#reference-counts" target="_blank" rel="noopener noreferrer">Python</a>)</li>
|
||
<li>Thread-local structures to prevent locking the allocator in
|
||
<a href="https://jamesgolick.com/2013/5/19/how-tcmalloc-works.html" target="_blank" rel="noopener noreferrer">tcmalloc</a></li>
|
||
<li>Arena structures used in <a href="http://jemalloc.net/" target="_blank" rel="noopener noreferrer">jemalloc</a>, which
|
||
<a href="https://blog.rust-lang.org/2019/01/17/Rust-1.32.0.html#jemalloc-is-removed-by-default" target="_blank" rel="noopener noreferrer">until recently</a>
|
||
was the primary allocator for Rust programs!</li>
|
||
</ul>
|
||
<p>But no matter how fast your allocator is, the principle remains: the fastest allocator is the one
|
||
you never use. As such, we're not going to discuss how exactly the
|
||
<a href="http://www.cs.virginia.edu/~evans/cs216/guides/x86.html" target="_blank" rel="noopener noreferrer"><code>push</code> and <code>pop</code> instructions work</a>, but
|
||
we'll focus instead on the conditions that enable the Rust compiler to use faster stack-based
|
||
allocation for variables.</p>
|
||
<p>So, <strong>how do we know when Rust will or will not use stack allocation for objects we create?</strong>
|
||
Looking at other languages, it's often easy to delineate between stack and heap. Managed memory
|
||
languages (Python, Java,
|
||
<a href="https://blogs.msdn.microsoft.com/ericlippert/2010/09/30/the-truth-about-value-types/" target="_blank" rel="noopener noreferrer">C#</a>) place
|
||
everything on the heap. JIT compilers (<a href="https://www.pypy.org/" target="_blank" rel="noopener noreferrer">PyPy</a>,
|
||
<a href="https://www.oracle.com/technetwork/java/javase/tech/index-jsp-136373.html" target="_blank" rel="noopener noreferrer">HotSpot</a>) may optimize
|
||
some heap allocations away, but you should never assume it will happen. C makes things clear with
|
||
calls to special functions (like <a href="https://linux.die.net/man/3/malloc" target="_blank" rel="noopener noreferrer">malloc(3)</a>) needed to access
|
||
heap memory. Old C++ has the <a href="https://stackoverflow.com/a/655086/1454178" target="_blank" rel="noopener noreferrer"><code>new</code></a> keyword, though
|
||
modern C++/C++11 is more complicated with <a href="https://en.cppreference.com/w/cpp/language/raii" target="_blank" rel="noopener noreferrer">RAII</a>.</p>
|
||
<p>For Rust, we can summarize as follows: <strong>stack allocation will be used for everything that doesn't
|
||
involve "smart pointers" and collections</strong>. We'll skip over a precise definition of the term "smart
|
||
pointer" for now, and instead discuss what we should watch for to understand when stack and heap
|
||
memory regions are used:</p>
|
||
<ol>
|
||
<li>
|
||
<p>Stack manipulation instructions (<code>push</code>, <code>pop</code>, and <code>add</code>/<code>sub</code> of the <code>rsp</code> register) indicate
|
||
allocation of stack memory:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">stack_alloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Space for `y` is allocated by subtracting from `rsp`,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// and then populated</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token number" style="color:hsl(35, 99%, 36%)">1u8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">3</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">4</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Space for `y` is deallocated by adding back to `rsp`</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/5WSgc9" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
</li>
|
||
<li>
|
||
<p>Tracking when exactly heap allocation calls occur is difficult. It's typically easier to watch
|
||
for <code>call core::ptr::real_drop_in_place</code>, and infer that a heap allocation happened in the recent
|
||
past:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">heap_alloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">usize</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">usize</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Space for elements in a vector has to be allocated</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// on the heap, and is then de-allocated once the</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// vector goes out of scope</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">with_capacity</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/epfgoQ" target="_blank" rel="noopener noreferrer">Compiler Explorer</a> (<code>real_drop_in_place</code> happens on line 1317)
|
||
<small>Note: While the
|
||
<a href="https://doc.rust-lang.org/std/ops/trait.Drop.html" target="_blank" rel="noopener noreferrer"><code>Drop</code> trait</a> is
|
||
<a href="https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=87edf374d8983816eb3d8cfeac657b46" target="_blank" rel="noopener noreferrer">called for stack-allocated objects</a>,
|
||
the Rust standard library only defines <code>Drop</code> implementations for types that involve heap
|
||
allocation.</small></p>
|
||
</li>
|
||
<li>
|
||
<p>If you don't want to inspect the assembly, use a custom allocator that's able to track and alert
|
||
when heap allocations occur. Crates like
|
||
<a href="https://crates.io/crates/alloc_counter" target="_blank" rel="noopener noreferrer"><code>alloc_counter</code></a> are designed for exactly this purpose.</p>
|
||
</li>
|
||
</ol>
|
||
<p>With all that in mind, let's talk about situations in which we're guaranteed to use stack memory:</p>
|
||
<ul>
|
||
<li>Structs are created on the stack.</li>
|
||
<li>Function arguments are passed on the stack, meaning the
|
||
<a href="https://doc.rust-lang.org/reference/attributes.html#inline-attribute" target="_blank" rel="noopener noreferrer"><code>#[inline]</code> attribute</a> will
|
||
not change the memory region used.</li>
|
||
<li>Enums and unions are stack-allocated.</li>
|
||
<li><a href="https://doc.rust-lang.org/std/primitive.array.html" target="_blank" rel="noopener noreferrer">Arrays</a> are always stack-allocated.</li>
|
||
<li>Closures capture their arguments on the stack.</li>
|
||
<li>Generics will use stack allocation, even with dynamic dispatch.</li>
|
||
<li><a href="https://doc.rust-lang.org/std/marker/trait.Copy.html" target="_blank" rel="noopener noreferrer"><code>Copy</code></a> types are guaranteed to be
|
||
stack-allocated, and copying them will be done in stack memory.</li>
|
||
<li><a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html" target="_blank" rel="noopener noreferrer"><code>Iterator</code>s</a> in the standard library are
|
||
stack-allocated even when iterating over heap-based collections.</li>
|
||
</ul>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="structs">Structs<a href="https://speice.io/2019/02/stacking-up#structs" class="hash-link" aria-label="Direct link to Structs" title="Direct link to Structs"></a></h2>
|
||
<p>The simplest case comes first. When creating vanilla <code>struct</code> objects, we use stack memory to hold
|
||
their contents:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u64</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u64</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">Line</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">make_line</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// `origin` is stored in the first 16 bytes of memory</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// starting at location `rsp`</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> origin </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// `point` makes up the next 16 bytes of memory</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> point </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">2</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// When creating `ray`, we just move the content out of</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// `origin` and `point` into the next 32 bytes of memory</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> ray </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Line</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> origin</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> point </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/vri9BE" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
<p>Note that while some extra-fancy instructions are used for memory manipulation in the assembly, the
|
||
<code>sub rsp, 64</code> instruction indicates we're still working with the stack.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="function-arguments">Function arguments<a href="https://speice.io/2019/02/stacking-up#function-arguments" class="hash-link" aria-label="Direct link to Function arguments" title="Direct link to Function arguments"></a></h2>
|
||
<p>Have you ever wondered how functions communicate with each other? Like, once the variables are given
|
||
to you, everything's fine. But how do you "give" those variables to another function? How do you get
|
||
the results back afterward? The answer: the compiler arranges memory and assembly instructions using
|
||
a pre-determined <a href="http://llvm.org/docs/LangRef.html#calling-conventions" target="_blank" rel="noopener noreferrer">calling convention</a>. This
|
||
convention governs the rules around where arguments needed by a function will be located (either in
|
||
memory offsets relative to the stack pointer <code>rsp</code>, or in other registers), and where the results
|
||
can be found once the function has finished. And when multiple languages agree on what the calling
|
||
conventions are, you can do things like having <a href="https://blog.filippo.io/rustgo/" target="_blank" rel="noopener noreferrer">Go call Rust code</a>!</p>
|
||
<p>Put simply: it's the compiler's job to figure out how to call other functions, and you can assume
|
||
that the compiler is good at its job.</p>
|
||
<p>We can see this in action using a simple example:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">i64</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">i64</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// We use integer division operations to keep</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// the assembly clean, understanding the result</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// isn't accurate.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">distance</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">i64</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Immediately subtract from `rsp` the bytes needed</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// to hold all the intermediate results - this is</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// the stack allocation step</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// The compiler used the `rdi` and `rsi` registers</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// to pass our arguments, so read them in</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Do the actual math work</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x_pow </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> x2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> x2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y_pow </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">y1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> y2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">y1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> y2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> squared </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> x_pow </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+</span><span class="token plain"> y_pow</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> squared </span><span class="token operator" style="color:hsl(221, 87%, 60%)">/</span><span class="token plain"> squared</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Our final result will be stored in the `rax` register</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// so that our caller knows where to retrieve it.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Finally, add back to `rsp` the stack memory that is</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// now ready to be used by other functions.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">total_distance</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> start </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">2</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> middle </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">3</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">4</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> end </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">5</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">6</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> _dist_1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">distance</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">start</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">middle</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> _dist_2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">distance</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">middle</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">end</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/Qmx4ST" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
<p>As a consequence of function arguments never using heap memory, we can also infer that functions
|
||
using the <code>#[inline]</code> attributes also do not heap allocate. But better than inferring, we can look
|
||
at the assembly to prove it:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">i64</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">i64</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Note that there is no `distance` function in the assembly output,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// and the total line count goes from 229 with inlining off</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// to 306 with inline on. Even still, no heap allocations occur.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[inline(always)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">distance</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">i64</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x_pow </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y_pow </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">y </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">y </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> squared </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> x_pow </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+</span><span class="token plain"> y_pow</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> squared </span><span class="token operator" style="color:hsl(221, 87%, 60%)">/</span><span class="token plain"> squared</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">total_distance</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> start </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">2</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> middle </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">3</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">4</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> end </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">5</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">6</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> _dist_1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">distance</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">start</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">middle</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> _dist_2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">distance</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">middle</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">end</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/30Sh66" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
<p>Finally, passing by value (arguments with type
|
||
<a href="https://doc.rust-lang.org/std/marker/trait.Copy.html" target="_blank" rel="noopener noreferrer"><code>Copy</code></a>) and passing by reference (either
|
||
moving ownership or passing a pointer) may have slightly different layouts in assembly, but will
|
||
still use either stack memory or CPU registers:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">i64</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">i64</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Moving values</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">distance_moved</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">i64</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x_pow </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> x2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> x2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y_pow </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">y1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> y2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">y1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> y2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> squared </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> x_pow </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+</span><span class="token plain"> y_pow</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> squared </span><span class="token operator" style="color:hsl(221, 87%, 60%)">/</span><span class="token plain"> squared</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Borrowing values has two extra `mov` instructions on lines 21 and 22</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">distance_borrowed</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Point</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">i64</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y2 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x_pow </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> x2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> x2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y_pow </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">y1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> y2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">y1 </span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token plain"> y2</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> squared </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> x_pow </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+</span><span class="token plain"> y_pow</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> squared </span><span class="token operator" style="color:hsl(221, 87%, 60%)">/</span><span class="token plain"> squared</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/06hGiv" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="enums">Enums<a href="https://speice.io/2019/02/stacking-up#enums" class="hash-link" aria-label="Direct link to Enums" title="Direct link to Enums"></a></h2>
|
||
<p>If you've ever worried that wrapping your types in
|
||
<a href="https://doc.rust-lang.org/stable/core/option/enum.Option.html" target="_blank" rel="noopener noreferrer"><code>Option</code></a> or
|
||
<a href="https://doc.rust-lang.org/stable/core/result/enum.Result.html" target="_blank" rel="noopener noreferrer"><code>Result</code></a> would finally make them
|
||
large enough that Rust decides to use heap allocation instead, fear no longer: <code>enum</code> and union
|
||
types don't use heap allocation:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">enum</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">MyEnum</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Small</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Large</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u64</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">MyStruct</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyEnum</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyEnum</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">enum_compare</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyEnum</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Small</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyEnum</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Large</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> z </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyStruct</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> y </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> opt </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Option</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Some</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">z</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/HK7zBx" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
<p>Because the size of an <code>enum</code> is the size of its largest element plus a flag, the compiler can
|
||
predict how much memory is used no matter which variant of an enum is currently stored in a
|
||
variable. Thus, enums and unions have no need of heap allocation. There's unfortunately not a great
|
||
way to show this in assembly, so I'll instead point you to the
|
||
<a href="https://doc.rust-lang.org/stable/core/mem/fn.size_of.html#size-of-enums" target="_blank" rel="noopener noreferrer"><code>core::mem::size_of</code></a>
|
||
documentation.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="arrays">Arrays<a href="https://speice.io/2019/02/stacking-up#arrays" class="hash-link" aria-label="Direct link to Arrays" title="Direct link to Arrays"></a></h2>
|
||
<p>The array type is guaranteed to be stack allocated, which is why the array size must be declared.
|
||
Interestingly enough, this can be used to cause safe Rust programs to crash:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)">// 256 bytes</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[derive(Default)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">TwoFiftySix</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> _a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u64</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// 8 kilobytes</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[derive(Default)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">EightK</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> _a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">TwoFiftySix</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// 256 kilobytes</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[derive(Default)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">TwoFiftySixK</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> _a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">EightK</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// 8 megabytes - exceeds space typically provided for the stack,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// though the kernel can be instructed to allocate more.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// On Linux, you can check stack size using `ulimit -s`</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[derive(Default)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">EightM</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> _a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">TwoFiftySixK</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Because we already have things in stack memory</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// (like the current function call stack), allocating another</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// eight megabytes of stack memory crashes the program</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> _x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">EightM</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">default</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>--
|
||
<a href="https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=587a6380a4914bcbcef4192c90c01dc4" target="_blank" rel="noopener noreferrer">Rust Playground</a></p>
|
||
<p>There aren't any security implications of this (no memory corruption occurs), but it's good to note
|
||
that the Rust compiler won't move arrays into heap memory even if they can be reasonably expected to
|
||
overflow the stack.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="closures">Closures<a href="https://speice.io/2019/02/stacking-up#closures" class="hash-link" aria-label="Direct link to Closures" title="Direct link to Closures"></a></h2>
|
||
<p>Rules for how anonymous functions capture their arguments are typically language-specific. In Java,
|
||
<a href="https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html" target="_blank" rel="noopener noreferrer">Lambda Expressions</a> are
|
||
actually objects created on the heap that capture local primitives by copying, and capture local
|
||
non-primitives as (<code>final</code>) references.
|
||
<a href="https://docs.python.org/3.7/reference/expressions.html#lambda" target="_blank" rel="noopener noreferrer">Python</a> and
|
||
<a href="https://javascriptweblog.wordpress.com/2010/10/25/understanding-javascript-closures/" target="_blank" rel="noopener noreferrer">JavaScript</a>
|
||
both bind <em>everything</em> by reference normally, but Python can also
|
||
<a href="https://stackoverflow.com/a/235764/1454178" target="_blank" rel="noopener noreferrer">capture values</a> and JavaScript has
|
||
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions" target="_blank" rel="noopener noreferrer">Arrow functions</a>.</p>
|
||
<p>In Rust, arguments to closures are the same as arguments to other functions; closures are simply
|
||
functions that don't have a declared name. Some weird ordering of the stack may be required to
|
||
handle them, but it's the compiler's responsiblity to figure that out.</p>
|
||
<p>Each example below has the same effect, but a different assembly implementation. In the simplest
|
||
case, we immediately run a closure returned by another function. Because we don't store a reference
|
||
to the closure, the stack memory needed to store the captured values is contiguous:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">my_func</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">impl</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">FnOnce</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">24</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Note that this closure in assembly looks exactly like</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// any other function; you even use the `call` instruction</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// to start running it.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">move</span><span class="token plain"> </span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">immediate</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">my_func</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">my_func</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/mgJ2zl" target="_blank" rel="noopener noreferrer">Compiler Explorer</a>, 25 total assembly instructions</p>
|
||
<p>If we store a reference to the closure, the Rust compiler keeps values it needs in the stack memory
|
||
of the original function. Getting the details right is a bit harder, so the instruction count goes
|
||
up even though this code is functionally equivalent to our original example:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">simple_reference</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">my_func</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">my_func</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/K_dj5n" target="_blank" rel="noopener noreferrer">Compiler Explorer</a>, 55 total assembly instructions</p>
|
||
<p>Even things like variable order can make a difference in instruction count:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">complex</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">my_func</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> y </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">my_func</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/p37qFl" target="_blank" rel="noopener noreferrer">Compiler Explorer</a>, 70 total assembly instructions</p>
|
||
<p>In every circumstance though, the compiler ensured that no heap allocations were necessary.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="generics">Generics<a href="https://speice.io/2019/02/stacking-up#generics" class="hash-link" aria-label="Direct link to Generics" title="Direct link to Generics"></a></h2>
|
||
<p>Traits in Rust come in two broad forms: static dispatch (monomorphization, <code>impl Trait</code>) and dynamic
|
||
dispatch (trait objects, <code>dyn Trait</code>). While dynamic dispatch is often <em>associated</em> with trait
|
||
objects being stored in the heap, dynamic dispatch can be used with stack allocated objects as well:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">trait</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">GetInt</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">get_int</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u64</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// vtable stored at section L__unnamed_1</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">WhyNotU8</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">impl</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">GetInt</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">for</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">WhyNotU8</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">get_int</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u64</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">as</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u64</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// vtable stored at section L__unnamed_2</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">ActualU64</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u64</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">impl</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">GetInt</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">for</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">ActualU64</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">get_int</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u64</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// `&dyn` declares that we want to use dynamic dispatch</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// rather than monomorphization, so there is only one</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// `retrieve_int` function that shows up in the final assembly.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// If we used generics, there would be one implementation of</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// `retrieve_int` for each type that implements `GetInt`.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">retrieve_int</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">u</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">dyn</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">GetInt</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// In the assembly, we just call an address given to us</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// in the `rsi` register and hope that it was set up</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// correctly when this function was invoked.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> u</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">get_int</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">do_call</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Note that even though the vtable for `WhyNotU8` and</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// `ActualU64` includes a pointer to</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// `core::ptr::real_drop_in_place`, it is never invoked.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> a </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">WhyNotU8</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> b </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">ActualU64</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">retrieve_int</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">a</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">retrieve_int</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">b</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/u_yguS" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
<p>It's hard to imagine practical situations where dynamic dispatch would be used for objects that
|
||
aren't heap allocated, but it technically can be done.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="copy-types">Copy types<a href="https://speice.io/2019/02/stacking-up#copy-types" class="hash-link" aria-label="Direct link to Copy types" title="Direct link to Copy types"></a></h2>
|
||
<p>Understanding move semantics and copy semantics in Rust is weird at first. The Rust docs
|
||
<a href="https://doc.rust-lang.org/stable/core/marker/trait.Copy.html" target="_blank" rel="noopener noreferrer">go into detail</a> far better than can
|
||
be addressed here, so I'll leave them to do the job. From a memory perspective though, their
|
||
guideline is reasonable:
|
||
<a href="https://doc.rust-lang.org/stable/core/marker/trait.Copy.html#when-should-my-type-be-copy" target="_blank" rel="noopener noreferrer">if your type can implemement <code>Copy</code>, it should</a>.
|
||
While there are potential speed tradeoffs to <em>benchmark</em> when discussing <code>Copy</code> (move semantics for
|
||
stack objects vs. copying stack pointers vs. copying stack <code>struct</code>s), <em>it's impossible for <code>Copy</code>
|
||
to introduce a heap allocation</em>.</p>
|
||
<p>But why is this the case? Fundamentally, it's because the language controls what <code>Copy</code> means -
|
||
<a href="https://doc.rust-lang.org/std/marker/trait.Copy.html#whats-the-difference-between-copy-and-clone" target="_blank" rel="noopener noreferrer">"the behavior of <code>Copy</code> is not overloadable"</a>
|
||
because it's a marker trait. From there we'll note that a type
|
||
<a href="https://doc.rust-lang.org/std/marker/trait.Copy.html#when-can-my-type-be-copy" target="_blank" rel="noopener noreferrer">can implement <code>Copy</code></a>
|
||
if (and only if) its components implement <code>Copy</code>, and that
|
||
<a href="https://doc.rust-lang.org/std/marker/trait.Copy.html#implementors" target="_blank" rel="noopener noreferrer">no heap-allocated types implement <code>Copy</code></a>.
|
||
Thus, assignments involving heap types are always move semantics, and new heap allocations won't
|
||
occur because of implicit operator behavior.</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[derive(Clone)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">Cloneable</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Box</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u64</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// error[E0204]: the trait `Copy` may not be implemented for this type</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[derive(Copy, Clone)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">NotCopyable</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Box</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u64</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/VToRuK" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="iterators">Iterators<a href="https://speice.io/2019/02/stacking-up#iterators" class="hash-link" aria-label="Direct link to Iterators" title="Direct link to Iterators"></a></h2>
|
||
<p>In managed memory languages (like
|
||
<a href="https://www.youtube.com/watch?v=bSkpMdDe4g4&feature=youtu.be&t=357" target="_blank" rel="noopener noreferrer">Java</a>), there's a subtle
|
||
difference between these two code samples:</p>
|
||
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">public</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">int</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">sum_for</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">List</span><span class="token generics punctuation" style="color:hsl(119, 34%, 47%)"><</span><span class="token generics class-name" style="color:hsl(35, 99%, 36%)">Long</span><span class="token generics punctuation" style="color:hsl(119, 34%, 47%)">></span><span class="token plain"> vals</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">long</span><span class="token plain"> sum </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Regular for loop</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">int</span><span class="token plain"> i </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> i </span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token plain"> vals</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">length</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> i</span><span class="token operator" style="color:hsl(221, 87%, 60%)">++</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> sum </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+=</span><span class="token plain"> vals</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token plain">i</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> sum</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">public</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">int</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">sum_foreach</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">List</span><span class="token generics punctuation" style="color:hsl(119, 34%, 47%)"><</span><span class="token generics class-name" style="color:hsl(35, 99%, 36%)">Long</span><span class="token generics punctuation" style="color:hsl(119, 34%, 47%)">></span><span class="token plain"> vals</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">long</span><span class="token plain"> sum </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// "Foreach" loop - uses iteration</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Long</span><span class="token plain"> l </span><span class="token operator" style="color:hsl(221, 87%, 60%)">:</span><span class="token plain"> vals</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> sum </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+=</span><span class="token plain"> l</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">return</span><span class="token plain"> sum</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>In the <code>sum_for</code> function, nothing terribly interesting happens. In <code>sum_foreach</code>, an object of type
|
||
<a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Iterator.html" target="_blank" rel="noopener noreferrer"><code>Iterator</code></a>
|
||
is allocated on the heap, and will eventually be garbage-collected. This isn't a great design;
|
||
iterators are often transient objects that you need during a function and can discard once the
|
||
function ends. Sounds exactly like the issue stack-allocated objects address, no?</p>
|
||
<p>In Rust, iterators are allocated on the stack. The objects to iterate over are almost certainly in
|
||
heap memory, but the iterator itself
|
||
(<a href="https://doc.rust-lang.org/std/slice/struct.Iter.html" target="_blank" rel="noopener noreferrer"><code>Iter</code></a>) doesn't need to use the heap. In
|
||
each of the examples below we iterate over a collection, but never use heap allocation:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">collections</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">HashMap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// There's a lot of assembly generated, but if you search in the text,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// there are no references to `real_drop_in_place` anywhere.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">sum_vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> s </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Basic iteration over vectors doesn't need allocation</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">for</span><span class="token plain"> y </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">in</span><span class="token plain"> x </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> s </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+=</span><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">sum_enumerate</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> s </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// More complex iterators are just fine too</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">for</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">_i</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">in</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">iter</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">enumerate</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> s </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+=</span><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">sum_hm</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">HashMap</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> s </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// And it's not just Vec, all types will allocate the iterator</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// on stack memory</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">for</span><span class="token plain"> y </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">in</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">values</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> s </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+=</span><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/FTT3CT" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[Allocations in Rust: Global memory]]></title>
|
||
<link>https://speice.io/2019/02/the-whole-world</link>
|
||
<guid>https://speice.io/2019/02/the-whole-world</guid>
|
||
<pubDate>Tue, 05 Feb 2019 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[The first memory type we'll look at is pretty special: when Rust can prove that a value is fixed]]></description>
|
||
<content:encoded><![CDATA[<p>The first memory type we'll look at is pretty special: when Rust can prove that a <em>value</em> is fixed
|
||
for the life of a program (<code>const</code>), and when a <em>reference</em> is unique for the life of a program
|
||
(<code>static</code> as a declaration, not
|
||
<a href="https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#the-static-lifetime" target="_blank" rel="noopener noreferrer"><code>'static</code></a> as a
|
||
lifetime), we can make use of global memory. This special section of data is embedded directly in
|
||
the program binary so that variables are ready to go once the program loads; no additional
|
||
computation is necessary.</p>
|
||
<p>Understanding the value/reference distinction is important for reasons we'll go into below, and
|
||
while the
|
||
<a href="https://github.com/rust-lang/rfcs/blob/master/text/0246-const-vs-static.md" target="_blank" rel="noopener noreferrer">full specification</a> for
|
||
these two keywords is available, we'll take a hands-on approach to the topic.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="const-values"><code>const</code> values<a href="https://speice.io/2019/02/the-whole-world#const-values" class="hash-link" aria-label="Direct link to const-values" title="Direct link to const-values"></a></h2>
|
||
<p>When a <em>value</em> is guaranteed to be unchanging in your program (where "value" may be scalars,
|
||
<code>struct</code>s, etc.), you can declare it <code>const</code>. This tells the compiler that it's safe to treat the
|
||
value as never changing, and enables some interesting optimizations; not only is there no
|
||
initialization cost to creating the value (it is loaded at the same time as the executable parts of
|
||
your program), but the compiler can also copy the value around if it speeds up the code.</p>
|
||
<p>The points we need to address when talking about <code>const</code> are:</p>
|
||
<ul>
|
||
<li><code>Const</code> values are stored in read-only memory - it's impossible to modify.</li>
|
||
<li>Values resulting from calling a <code>const fn</code> are materialized at compile-time.</li>
|
||
<li>The compiler may (or may not) copy <code>const</code> values wherever it chooses.</li>
|
||
</ul>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="read-only">Read-Only<a href="https://speice.io/2019/02/the-whole-world#read-only" class="hash-link" aria-label="Direct link to Read-Only" title="Direct link to Read-Only"></a></h3>
|
||
<p>The first point is a bit strange - "read-only memory."
|
||
<a href="https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants" target="_blank" rel="noopener noreferrer">The Rust book</a>
|
||
mentions in a couple places that using <code>mut</code> with constants is illegal, but it's also important to
|
||
demonstrate just how immutable they are. <em>Typically</em> in Rust you can use
|
||
<a href="https://doc.rust-lang.org/book/ch15-05-interior-mutability.html" target="_blank" rel="noopener noreferrer">interior mutability</a> to modify
|
||
things that aren't declared <code>mut</code>.
|
||
<a href="https://doc.rust-lang.org/std/cell/struct.RefCell.html" target="_blank" rel="noopener noreferrer"><code>RefCell</code></a> provides an example of this
|
||
pattern in action:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">cell</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">my_mutator</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">cell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Even though we're given an immutable reference,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// the `replace` method allows us to modify the inner value.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> cell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">replace</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">14</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> cell </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">25</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Prints out 25</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">println!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"Cell: {:?}"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> cell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">my_mutator</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">cell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Prints out 14</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">println!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"Cell: {:?}"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> cell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>--
|
||
<a href="https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8e4bea1a718edaff4507944e825a54b2" target="_blank" rel="noopener noreferrer">Rust Playground</a></p>
|
||
<p>When <code>const</code> is involved though, interior mutability is impossible:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">cell</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">const</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">CELL</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">25</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">my_mutator</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">cell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> cell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">replace</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">14</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// First line prints 25 as expected</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">println!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"Cell: {:?}"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token constant" style="color:hsl(35, 99%, 36%)">CELL</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">my_mutator</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token constant" style="color:hsl(35, 99%, 36%)">CELL</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Second line *still* prints 25</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">println!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"Cell: {:?}"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token constant" style="color:hsl(35, 99%, 36%)">CELL</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>--
|
||
<a href="https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=88fe98110c33c1b3a51e341f48b8ae00" target="_blank" rel="noopener noreferrer">Rust Playground</a></p>
|
||
<p>And a second example using <a href="https://doc.rust-lang.org/std/sync/struct.Once.html" target="_blank" rel="noopener noreferrer"><code>Once</code></a>:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">sync</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Once</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">const</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">SURPRISE</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Once</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Once</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// This is how `Once` is supposed to be used</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">SURPRISE</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">call_once</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">println!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"Initializing..."</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Because `Once` is a `const` value, we never record it</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// having been initialized the first time, and this closure</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// will also execute.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">SURPRISE</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">call_once</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">println!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"Initializing again???"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>--
|
||
<a href="https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c3cc5979b5e5434eca0f9ec4a06ee0ed" target="_blank" rel="noopener noreferrer">Rust Playground</a></p>
|
||
<p>When the
|
||
<a href="https://github.com/rust-lang/rfcs/blob/26197104b7bb9a5a35db243d639aee6e46d35d75/text/0246-const-vs-static.md" target="_blank" rel="noopener noreferrer"><code>const</code> specification</a>
|
||
refers to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3055.pdf" target="_blank" rel="noopener noreferrer">"rvalues"</a>, this
|
||
behavior is what they refer to. <a href="https://github.com/rust-lang/rust-clippy" target="_blank" rel="noopener noreferrer">Clippy</a> will treat this
|
||
as an error, but it's still something to be aware of.</p>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="initialization">Initialization<a href="https://speice.io/2019/02/the-whole-world#initialization" class="hash-link" aria-label="Direct link to Initialization" title="Direct link to Initialization"></a></h3>
|
||
<p>The next thing to mention is that <code>const</code> values are loaded into memory <em>as part of your program
|
||
binary</em>. Because of this, any <code>const</code> values declared in your program will be "realized" at
|
||
compile-time; accessing them may trigger a main-memory lookup (with a fixed address, so your CPU may
|
||
be able to prefetch the value), but that's it.</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">cell</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">const</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">CELL</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">24</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">multiply</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">value</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// CELL is stored at `.L__unnamed_1`</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> value </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token constant" style="color:hsl(35, 99%, 36%)">CELL</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">get_mut</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/Th8boO" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
<p>The compiler creates one <code>RefCell</code>, uses it everywhere, and never needs to call the <code>RefCell::new</code>
|
||
function.</p>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="copying">Copying<a href="https://speice.io/2019/02/the-whole-world#copying" class="hash-link" aria-label="Direct link to Copying" title="Direct link to Copying"></a></h3>
|
||
<p>If it's helpful though, the compiler can choose to copy <code>const</code> values.</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">const</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">FACTOR</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1000</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">multiply</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">value</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// See assembly line 4 for the `mov edi, 1000` instruction</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> value </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">FACTOR</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">multiply_twice</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">value</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// See assembly lines 22 and 29 for `mov edi, 1000` instructions</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> value </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">FACTOR</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">FACTOR</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/ZtS54X" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
<p>In this example, the <code>FACTOR</code> value is turned into the <code>mov edi, 1000</code> instruction in both the
|
||
<code>multiply</code> and <code>multiply_twice</code> functions; the "1000" value is never "stored" anywhere, as it's
|
||
small enough to inline into the assembly instructions.</p>
|
||
<p>Finally, getting the address of a <code>const</code> value is possible, but not guaranteed to be unique
|
||
(because the compiler can choose to copy values). I was unable to get non-unique pointers in my
|
||
testing (even using different crates), but the specifications are clear enough: <em>don't rely on
|
||
pointers to <code>const</code> values being consistent</em>. To be frank, caring about locations for <code>const</code> values
|
||
is almost certainly a code smell.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="static-values"><code>static</code> values<a href="https://speice.io/2019/02/the-whole-world#static-values" class="hash-link" aria-label="Direct link to static-values" title="Direct link to static-values"></a></h2>
|
||
<p>Static variables are related to <code>const</code> variables, but take a slightly different approach. When we
|
||
declare that a <em>reference</em> is unique for the life of a program, you have a <code>static</code> variable
|
||
(unrelated to the <code>'static</code> lifetime). Because of the reference/value distinction with
|
||
<code>const</code>/<code>static</code>, static variables behave much more like typical "global" variables.</p>
|
||
<p>But to understand <code>static</code>, here's what we'll look at:</p>
|
||
<ul>
|
||
<li><code>static</code> variables are globally unique locations in memory.</li>
|
||
<li>Like <code>const</code>, <code>static</code> variables are loaded at the same time as your program being read into
|
||
memory.</li>
|
||
<li>All <code>static</code> variables must implement the
|
||
<a href="https://doc.rust-lang.org/std/marker/trait.Sync.html" target="_blank" rel="noopener noreferrer"><code>Sync</code></a> marker trait.</li>
|
||
<li>Interior mutability is safe and acceptable when using <code>static</code> variables.</li>
|
||
</ul>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="memory-uniqueness">Memory Uniqueness<a href="https://speice.io/2019/02/the-whole-world#memory-uniqueness" class="hash-link" aria-label="Direct link to Memory Uniqueness" title="Direct link to Memory Uniqueness"></a></h3>
|
||
<p>The single biggest difference between <code>const</code> and <code>static</code> is the guarantees provided about
|
||
uniqueness. Where <code>const</code> variables may or may not be copied in code, <code>static</code> variables are
|
||
guarantee to be unique. If we take a previous <code>const</code> example and change it to <code>static</code>, the
|
||
difference should be clear:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">FACTOR</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">1000</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">multiply</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">value</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> value </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">FACTOR</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">multiply_twice</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">value</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// The assembly to `mul dword ptr [rip + example::FACTOR]` is how FACTOR gets used</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> value </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">FACTOR</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">*</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">FACTOR</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>-- <a href="https://godbolt.org/z/uxmiRQ" target="_blank" rel="noopener noreferrer">Compiler Explorer</a></p>
|
||
<p>Where <a href="https://speice.io/2019/02/the-whole-world#copying">previously</a> there were plenty of references to multiplying by 1000, the new
|
||
assembly refers to <code>FACTOR</code> as a named memory location instead. No initialization work needs to be
|
||
done, but the compiler can no longer prove the value never changes during execution.</p>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="initialization-1">Initialization<a href="https://speice.io/2019/02/the-whole-world#initialization-1" class="hash-link" aria-label="Direct link to Initialization" title="Direct link to Initialization"></a></h3>
|
||
<p>Next, let's talk about initialization. The simplest case is initializing static variables with
|
||
either scalar or struct notation:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[derive(Debug)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">MyStruct</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">MY_STRUCT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyStruct</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyStruct</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// You can even reference other statics</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// declared later</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">MY_VAL</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">MY_VAL</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">24</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">println!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"Static MyStruct: {:?}"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">MY_STRUCT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>--
|
||
<a href="https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b538dbc46076f12db047af4f4403ee6e" target="_blank" rel="noopener noreferrer">Rust Playground</a></p>
|
||
<p>Things can get a bit weirder when using <code>const fn</code> though. In most cases, it just works:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[derive(Debug)]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">MyStruct</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">impl</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyStruct</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">const</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyStruct</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyStruct</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">24</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">MY_STRUCT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyStruct</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyStruct</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">println!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"const fn Static MyStruct: {:?}"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">MY_STRUCT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>--
|
||
<a href="https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8c796a6e7fc273c12115091b707b0255" target="_blank" rel="noopener noreferrer">Rust Playground</a></p>
|
||
<p>However, there's a caveat: you're currently not allowed to use <code>const fn</code> to initialize static
|
||
variables of types that aren't marked <code>Sync</code>. For example,
|
||
<a href="https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.new" target="_blank" rel="noopener noreferrer"><code>RefCell::new()</code></a> is a
|
||
<code>const fn</code>, but because
|
||
<a href="https://doc.rust-lang.org/std/cell/struct.RefCell.html#impl-Sync" target="_blank" rel="noopener noreferrer"><code>RefCell</code> isn't <code>Sync</code></a>, you'll
|
||
get an error at compile time:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">cell</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">MY_LOCK</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>--
|
||
<a href="https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c76ef86e473d07117a1700e21fd45560" target="_blank" rel="noopener noreferrer">Rust Playground</a></p>
|
||
<p>It's likely that this will
|
||
<a href="https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md" target="_blank" rel="noopener noreferrer">change in the future</a> though.</p>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-sync-marker">The <code>Sync</code> marker<a href="https://speice.io/2019/02/the-whole-world#the-sync-marker" class="hash-link" aria-label="Direct link to the-sync-marker" title="Direct link to the-sync-marker"></a></h3>
|
||
<p>Which leads well to the next point: static variable types must implement the
|
||
<a href="https://doc.rust-lang.org/std/marker/trait.Sync.html" target="_blank" rel="noopener noreferrer"><code>Sync</code> marker</a>. Because they're globally
|
||
unique, it must be safe for you to access static variables from any thread at any time. Most
|
||
<code>struct</code> definitions automatically implement the <code>Sync</code> trait because they contain only elements
|
||
which themselves implement <code>Sync</code> (read more in the
|
||
<a href="https://doc.rust-lang.org/nomicon/send-and-sync.html" target="_blank" rel="noopener noreferrer">Nomicon</a>). This is why earlier examples could
|
||
get away with initializing statics, even though we never included an <code>impl Sync for MyStruct</code> in the
|
||
code. To demonstrate this property, Rust refuses to compile our earlier example if we add a
|
||
non-<code>Sync</code> element to the <code>struct</code> definition:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">cell</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">MyStruct</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// error[E0277]: `std::cell::RefCell<u8>` cannot be shared between threads safely</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">MY_STRUCT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyStruct</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyStruct</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">RefCell</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>--
|
||
<a href="https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=40074d0248f056c296b662dbbff97cfc" target="_blank" rel="noopener noreferrer">Rust Playground</a></p>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="interior-mutability">Interior mutability<a href="https://speice.io/2019/02/the-whole-world#interior-mutability" class="hash-link" aria-label="Direct link to Interior mutability" title="Direct link to Interior mutability"></a></h3>
|
||
<p>Finally, while <code>static mut</code> variables are allowed, mutating them is an <code>unsafe</code> operation. If we
|
||
want to stay in <code>safe</code> Rust, we can use interior mutability to accomplish similar goals:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">sync</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Once</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// This example adapted from https://doc.rust-lang.org/std/sync/struct.Once.html#method.call_once</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">INIT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Once</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Once</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Note that while `INIT` is declared immutable, we're still allowed</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// to mutate its interior</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">INIT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">call_once</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">println!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"Initializing..."</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// This code won't panic, as the interior of INIT was modified</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// as part of the previous `call_once`</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">INIT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">call_once</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">panic!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"INIT was called twice!"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>--
|
||
<a href="https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=3ba003a981a7ed7400240caadd384d59" target="_blank" rel="noopener noreferrer">Rust Playground</a></p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[Allocations in Rust: Foreword]]></title>
|
||
<link>https://speice.io/2019/02/understanding-allocations-in-rust</link>
|
||
<guid>https://speice.io/2019/02/understanding-allocations-in-rust</guid>
|
||
<pubDate>Mon, 04 Feb 2019 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[There's an alchemy of distilling complex technical topics into articles and videos that change the]]></description>
|
||
<content:encoded><![CDATA[<p>There's an alchemy of distilling complex technical topics into articles and videos that change the
|
||
way programmers see the tools they interact with on a regular basis. I knew what a linker was, but
|
||
there's a staggering amount of complexity in between
|
||
<a href="https://www.youtube.com/watch?v=dOfucXtyEsU" target="_blank" rel="noopener noreferrer">the OS and <code>main()</code></a>. Rust programmers use the
|
||
<a href="https://doc.rust-lang.org/stable/std/boxed/struct.Box.html" target="_blank" rel="noopener noreferrer"><code>Box</code></a> type all the time, but there's a
|
||
rich history of the Rust language itself wrapped up in
|
||
<a href="https://manishearth.github.io/blog/2017/01/10/rust-tidbits-box-is-special/" target="_blank" rel="noopener noreferrer">how special it is</a>.</p>
|
||
<p>In a similar vein, this series attempts to look at code and understand how memory is used; the
|
||
complex choreography of operating system, compiler, and program that frees you to focus on
|
||
functionality far-flung from frivolous book-keeping. The Rust compiler relieves a great deal of the
|
||
cognitive burden associated with memory management, but we're going to step into its world for a
|
||
while.</p>
|
||
<p>Let's learn a bit about memory in Rust.</p>
|
||
<hr>
|
||
<p>Rust's three defining features of
|
||
<a href="https://www.rust-lang.org/" target="_blank" rel="noopener noreferrer">Performance, Reliability, and Productivity</a> are all driven to a great
|
||
degree by the how the Rust compiler understands memory usage. Unlike managed memory languages (Java,
|
||
Python), Rust
|
||
<a href="https://words.steveklabnik.com/borrow-checking-escape-analysis-and-the-generational-hypothesis" target="_blank" rel="noopener noreferrer">doesn't really</a>
|
||
garbage collect; instead, it uses an
|
||
<a href="https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html" target="_blank" rel="noopener noreferrer">ownership</a> system to reason about
|
||
how long objects will last in your program. In some cases, if the life of an object is fairly
|
||
transient, Rust can make use of a very fast region called the "stack." When that's not possible,
|
||
Rust uses
|
||
<a href="https://en.wikipedia.org/wiki/Memory_management#Dynamic_memory_allocation" target="_blank" rel="noopener noreferrer">dynamic (heap) memory</a>
|
||
and the ownership system to ensure you can't accidentally corrupt memory. It's not as fast, but it
|
||
is important to have available.</p>
|
||
<p>That said, there are specific situations in Rust where you'd never need to worry about the
|
||
stack/heap distinction! If you:</p>
|
||
<ol>
|
||
<li>Never use <code>unsafe</code></li>
|
||
<li>Never use <code>#![feature(alloc)]</code> or the <a href="https://doc.rust-lang.org/alloc/index.html" target="_blank" rel="noopener noreferrer"><code>alloc</code> crate</a></li>
|
||
</ol>
|
||
<p>...then it's not possible for you to use dynamic memory!</p>
|
||
<p>For some uses of Rust, typically embedded devices, these constraints are OK. They have very limited
|
||
memory, and the program binary size itself may significantly affect what's available! There's no
|
||
operating system able to manage this
|
||
<a href="https://en.wikipedia.org/wiki/Virtual_memory" target="_blank" rel="noopener noreferrer">"virtual memory"</a> thing, but that's not an issue
|
||
because there's only one running application. The
|
||
<a href="https://docs.rust-embedded.org/embedonomicon/preface.html" target="_blank" rel="noopener noreferrer">embedonomicon</a> is ever in mind, and
|
||
interacting with the "real world" through extra peripherals is accomplished by reading and writing
|
||
to <a href="https://bob.cs.sonoma.edu/IntroCompOrg-RPi/sec-gpio-mem.html" target="_blank" rel="noopener noreferrer">specific memory addresses</a>.</p>
|
||
<p>Most Rust programs find these requirements overly burdensome though. C++ developers would struggle
|
||
without access to <a href="https://en.cppreference.com/w/cpp/container/vector" target="_blank" rel="noopener noreferrer"><code>std::vector</code></a> (except those
|
||
hardcore no-STL people), and Rust developers would struggle without
|
||
<a href="https://doc.rust-lang.org/std/vec/struct.Vec.html" target="_blank" rel="noopener noreferrer"><code>std::vec</code></a>. But with the constraints above,
|
||
<code>std::vec</code> is actually a part of the
|
||
<a href="https://doc.rust-lang.org/alloc/vec/struct.Vec.html" target="_blank" rel="noopener noreferrer"><code>alloc</code> crate</a>, and thus off-limits. <code>Box</code>,
|
||
<code>Rc</code>, etc., are also unusable for the same reason.</p>
|
||
<p>Whether writing code for embedded devices or not, the important thing in both situations is how much
|
||
you know <em>before your application starts</em> about what its memory usage will look like. In embedded
|
||
devices, there's a small, fixed amount of memory to use. In a browser, you have no idea how large
|
||
<a href="https://www.google.com/" target="_blank" rel="noopener noreferrer">google.com</a>'s home page is until you start trying to download it. The
|
||
compiler uses this knowledge (or lack thereof) to optimize how memory is used; put simply, your code
|
||
runs faster when the compiler can guarantee exactly how much memory your program needs while it's
|
||
running. This series is all about understanding how the compiler reasons about your program, with an
|
||
emphasis on the implications for performance.</p>
|
||
<p>Now let's address some conditions and caveats before going much further:</p>
|
||
<ul>
|
||
<li>We'll focus on "safe" Rust only; <code>unsafe</code> lets you use platform-specific allocation API's
|
||
(<a href="https://www.tutorialspoint.com/c_standard_library/c_function_malloc.htm" target="_blank" rel="noopener noreferrer"><code>malloc</code></a>) that we'll
|
||
ignore.</li>
|
||
<li>We'll assume a "debug" build of Rust code (what you get with <code>cargo run</code> and <code>cargo test</code>) and
|
||
address (pun intended) release mode at the end (<code>cargo run --release</code> and <code>cargo test --release</code>).</li>
|
||
<li>All content will be run using Rust 1.32, as that's the highest currently supported in the
|
||
<a href="https://godbolt.org/" target="_blank" rel="noopener noreferrer">Compiler Exporer</a>. As such, we'll avoid upcoming innovations like
|
||
<a href="https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md" target="_blank" rel="noopener noreferrer">compile-time evaluation of <code>static</code></a>
|
||
that are available in nightly.</li>
|
||
<li>Because of the nature of the content, being able to read assembly is helpful. We'll keep it
|
||
simple, but I <a href="https://stackoverflow.com/a/4584131/1454178" target="_blank" rel="noopener noreferrer">found</a> a
|
||
<a href="https://stackoverflow.com/a/26026278/1454178" target="_blank" rel="noopener noreferrer">refresher</a> on the <code>push</code> and <code>pop</code>
|
||
<a href="http://www.cs.virginia.edu/~evans/cs216/guides/x86.html" target="_blank" rel="noopener noreferrer">instructions</a> was helpful while writing
|
||
this.</li>
|
||
<li>I've tried to be precise in saying only what I can prove using the tools (ASM, docs) that are
|
||
available, but if there's something said in error it will be corrected expeditiously. Please let
|
||
me know at <a href="mailto:bradlee@speice.io" target="_blank" rel="noopener noreferrer">bradlee@speice.io</a></li>
|
||
</ul>
|
||
<p>Finally, I'll do what I can to flag potential future changes but the Rust docs have a notice worth
|
||
repeating:</p>
|
||
<blockquote>
|
||
<p>Rust does not currently have a rigorously and formally defined memory model.</p>
|
||
<p>-- <a href="https://doc.rust-lang.org/std/ptr/fn.read_volatile.html" target="_blank" rel="noopener noreferrer">the docs</a></p>
|
||
</blockquote>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[QADAPT - debug_assert! for allocations]]></title>
|
||
<link>https://speice.io/2018/12/allocation-safety</link>
|
||
<guid>https://speice.io/2018/12/allocation-safety</guid>
|
||
<pubDate>Sat, 15 Dec 2018 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[I think it's part of the human condition to ignore perfectly good advice when it comes our way. A]]></description>
|
||
<content:encoded><![CDATA[<p>I think it's part of the human condition to ignore perfectly good advice when it comes our way. A
|
||
bit over a month ago, I was dispensing sage wisdom for the ages:</p>
|
||
<blockquote>
|
||
<p>I had a really great idea: build a custom allocator that allows you to track your own allocations.
|
||
I gave it a shot, but learned very quickly: <strong>never write your own allocator.</strong></p>
|
||
<p>-- <a href="https://speice.io/2018/10/case-study-optimization">me</a></p>
|
||
</blockquote>
|
||
<p>I proceeded to ignore it, because we never really learn from our mistakes.</p>
|
||
<p>There's another part of the human condition that derives joy from seeing things explode.</p>
|
||
<center><p><img decoding="async" loading="lazy" alt="Explosions" src="https://speice.io/assets/images/watch-the-world-burn-630e740c91d090f5790a3f4e103f1142.webp" width="400" height="280" class="img_ev3q"></p></center>
|
||
<p>And <em>that's</em> the part I'm going to focus on.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-an-allocator">Why an Allocator?<a href="https://speice.io/2018/12/allocation-safety#why-an-allocator" class="hash-link" aria-label="Direct link to Why an Allocator?" title="Direct link to Why an Allocator?"></a></h2>
|
||
<p>So why, after complaining about allocators, would I still want to write one? There are three reasons
|
||
for that:</p>
|
||
<ol>
|
||
<li>Allocation/dropping is slow</li>
|
||
<li>It's difficult to know exactly when Rust will allocate or drop, especially when using code that
|
||
you did not write</li>
|
||
<li>I want automated tools to verify behavior, instead of inspecting by hand</li>
|
||
</ol>
|
||
<p>When I say "slow," it's important to define the terms. If you're writing web applications, you'll
|
||
spend orders of magnitude more time waiting for the database than you will the allocator. However,
|
||
there's still plenty of code where micro- or nano-seconds matter; think
|
||
<a href="https://www.youtube.com/watch?v=NH1Tta7purM" target="_blank" rel="noopener noreferrer">finance</a>,
|
||
<a href="https://www.reddit.com/r/rust/comments/9hg7yj/synthesizer_progress_update/e6c291f" target="_blank" rel="noopener noreferrer">real-time audio</a>,
|
||
<a href="https://polysync.io/blog/session-types-for-hearty-codecs/" target="_blank" rel="noopener noreferrer">self-driving cars</a>, and
|
||
<a href="https://carllerche.github.io/bytes/bytes/index.html" target="_blank" rel="noopener noreferrer">networking</a>. In these situations it's simply
|
||
unacceptable for you to spend time doing things that are not your program, and waiting on the
|
||
allocator is not cool.</p>
|
||
<p>As I continue to learn Rust, it's difficult for me to predict where exactly allocations will happen.
|
||
So, I propose we play a quick trivia game: <strong>Does this code invoke the allocator?</strong></p>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="example-1">Example 1<a href="https://speice.io/2018/12/allocation-safety#example-1" class="hash-link" aria-label="Direct link to Example 1" title="Direct link to Example 1"></a></h3>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">my_function</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> v</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p><strong>No</strong>: Rust <a href="https://doc.rust-lang.org/std/mem/fn.size_of.html" target="_blank" rel="noopener noreferrer">knows how big</a> the <code>Vec</code> type is,
|
||
and reserves a fixed amount of memory on the stack for the <code>v</code> vector. However, if we wanted to
|
||
reserve extra space (using <code>Vec::with_capacity</code>) the allocator would get invoked.</p>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="example-2">Example 2<a href="https://speice.io/2018/12/allocation-safety#example-2" class="hash-link" aria-label="Direct link to Example 2" title="Direct link to Example 2"></a></h3>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">my_function</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> v</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Box</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token operator" style="color:hsl(221, 87%, 60%)">>></span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Box</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p><strong>Yes</strong>: Because Boxes allow us to work with things that are of unknown size, it has to allocate on
|
||
the heap. While the <code>Box</code> is unnecessary in this snippet (release builds will optimize out the
|
||
allocation), reserving heap space more generally is needed to pass a dynamically sized type to
|
||
another function.</p>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="example-3">Example 3<a href="https://speice.io/2018/12/allocation-safety#example-3" class="hash-link" aria-label="Direct link to Example 3" title="Direct link to Example 3"></a></h3>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">my_function</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">v</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> v</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">push</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">5</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p><strong>Maybe</strong>: Depending on whether the Vector we were given has space available, we may or may not
|
||
allocate. Especially when dealing with code that you did not author, it's difficult to verify that
|
||
things behave as you expect them to.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="blowing-things-up">Blowing Things Up<a href="https://speice.io/2018/12/allocation-safety#blowing-things-up" class="hash-link" aria-label="Direct link to Blowing Things Up" title="Direct link to Blowing Things Up"></a></h2>
|
||
<p>So, how exactly does QADAPT solve these problems? <strong>Whenever an allocation or drop occurs in code
|
||
marked allocation-safe, QADAPT triggers a thread panic.</strong> We don't want to let the program continue
|
||
as if nothing strange happened, <em>we want things to explode</em>.</p>
|
||
<p>However, you don't want code to panic in production because of circumstances you didn't predict.
|
||
Just like <a href="https://doc.rust-lang.org/std/macro.debug_assert.html" target="_blank" rel="noopener noreferrer"><code>debug_assert!</code></a>, <strong>QADAPT will
|
||
strip out its own code when building in release mode to guarantee no panics and no performance
|
||
impact.</strong></p>
|
||
<p>Finally, there are three ways to have QADAPT check that your code will not invoke the allocator:</p>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="using-a-procedural-macro">Using a procedural macro<a href="https://speice.io/2018/12/allocation-safety#using-a-procedural-macro" class="hash-link" aria-label="Direct link to Using a procedural macro" title="Direct link to Using a procedural macro"></a></h3>
|
||
<p>The easiest method, watch an entire function for allocator invocation:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">qadapt</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token plain">no_alloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">qadapt</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token constant" style="color:hsl(35, 99%, 36%)">QADAPT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[global_allocator]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Q</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">QADAPT</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">QADAPT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[no_alloc]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">push_vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">v</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// This triggers a panic if v.len() == v.capacity()</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> v</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">push</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">5</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> v </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">with_capacity</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// This will *not* trigger a panic</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">push_vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">v</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// This *will* trigger a panic</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">push_vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">v</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="using-a-regular-macro">Using a regular macro<a href="https://speice.io/2018/12/allocation-safety#using-a-regular-macro" class="hash-link" aria-label="Direct link to Using a regular macro" title="Direct link to Using a regular macro"></a></h3>
|
||
<p>For times when you need more precision:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">qadapt</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token plain">assert_no_alloc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">qadapt</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token constant" style="color:hsl(35, 99%, 36%)">QADAPT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[global_allocator]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Q</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">QADAPT</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">QADAPT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> v </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">with_capacity</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// No allocations here, we already have space reserved</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">assert_no_alloc!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">v</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">push</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">5</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Even though we remove an item, it doesn't trigger a drop</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// because it's a scalar. If it were a `Box<_>` type,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// a drop would trigger.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">assert_no_alloc!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> v</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">pop</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">unwrap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="using-function-calls">Using function calls<a href="https://speice.io/2018/12/allocation-safety#using-function-calls" class="hash-link" aria-label="Direct link to Using function calls" title="Direct link to Using function calls"></a></h3>
|
||
<p>Both the most precise and most tedious:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">qadapt</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token plain">enter_protected</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">qadapt</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token plain">exit_protected</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">qadapt</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token constant" style="color:hsl(35, 99%, 36%)">QADAPT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[global_allocator]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Q</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">QADAPT</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">QADAPT</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// This triggers an allocation (on non-release builds)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> v </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">with_capacity</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">enter_protected</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// This does not trigger an allocation because we've reserved size</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> v</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">push</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">exit_protected</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// This triggers an allocation because we ran out of size,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// but doesn't panic because we're no longer protected.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> v</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">push</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="caveats">Caveats<a href="https://speice.io/2018/12/allocation-safety#caveats" class="hash-link" aria-label="Direct link to Caveats" title="Direct link to Caveats"></a></h3>
|
||
<p>It's important to point out that QADAPT code is synchronous, so please be careful when mixing in
|
||
asynchronous functions:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">futures</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">future</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Future</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">futures</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">future</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token plain">ok</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[no_alloc]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">async_capacity</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">impl</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Future</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Item</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u8</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Error</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">ok</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">12</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">and_then</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token closure-params">e</span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ok</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">with_capacity</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">e</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// This doesn't trigger a panic because the `and_then` closure</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// wasn't run during the function call.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">async_capacity</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Still no panic</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">assert_no_alloc!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token function" style="color:hsl(221, 87%, 60%)">async_capacity</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// This will panic because the allocation happens during `unwrap`</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// in the `assert_no_alloc!` macro</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">assert_no_alloc!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token function" style="color:hsl(221, 87%, 60%)">async_capacity</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">poll</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">unwrap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://speice.io/2018/12/allocation-safety#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion"></a></h2>
|
||
<p>While there's a lot more to writing high-performance code than managing your usage of the allocator,
|
||
it's critical that you do use the allocator correctly. QADAPT will verify that your code is doing
|
||
what you expect. It's usable even on stable Rust from version 1.31 onward, which isn't the case for
|
||
most allocators. Version 1.0 was released today, and you can check it out over at
|
||
<a href="https://crates.io/crates/qadapt" target="_blank" rel="noopener noreferrer">crates.io</a> or on <a href="https://github.com/bspeice/qadapt" target="_blank" rel="noopener noreferrer">github</a>.</p>
|
||
<p>I'm hoping to write more about high-performance Rust in the future, and I expect that QADAPT will
|
||
help guide that. If there are topics you're interested in, let me know in the comments below!</p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[More "what companies really mean"]]></title>
|
||
<link>https://speice.io/2018/12/what-small-business-really-means</link>
|
||
<guid>https://speice.io/2018/12/what-small-business-really-means</guid>
|
||
<pubDate>Tue, 04 Dec 2018 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[I recently stumbled across a phenomenal small article entitled]]></description>
|
||
<content:encoded><![CDATA[<p>I recently stumbled across a phenomenal small article entitled
|
||
<a href="https://angel.co/blog/what-startups-really-mean-by-why-should-we-hire-you" target="_blank" rel="noopener noreferrer">What Startups Really Mean By "Why Should We Hire You?"</a>.
|
||
Having been interviewed by smaller companies (though not exactly startups), the questions and
|
||
subtexts are the same. There's often a question behind the question that you're actually trying to
|
||
answer, and I wish I spotted the nuance earlier in my career.</p>
|
||
<p>Let me also make note of one more question/euphemism I've come across:</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-you-feel-about-production-support">How do you feel about production support?<a href="https://speice.io/2018/12/what-small-business-really-means#how-do-you-feel-about-production-support" class="hash-link" aria-label="Direct link to How do you feel about production support?" title="Direct link to How do you feel about production support?"></a></h2>
|
||
<p><strong>Translation</strong>: <em>We're a fairly small team, and when things break on an evening/weekend/Christmas
|
||
Day, can we call on you to be there?</em></p>
|
||
<p>I've met decidedly few people in my life who truly enjoy the "ops" side of "devops". They're
|
||
incredibly good at taking an impossible problem, pre-existing knowledge of arcane arts, and turning
|
||
that into a functioning system at the end. And if they all left for lunch, we probably wouldn't make
|
||
it out the door before the zombie apocalypse.</p>
|
||
<p>Larger organizations (in my experience, 500+ person organizations) have the luxury of hiring people
|
||
who either enjoy that, or play along nicely enough that our systems keep working.</p>
|
||
<p>Small teams have no such luck. If you're interviewing at a small company, especially as a "data
|
||
scientist" or other somesuch position, be aware that systems can and do spontaneously combust at the
|
||
most inopportune moments.</p>
|
||
<p><strong>Terrible-but-popular answers include</strong>: <em>It's a part of the job, and I'm happy to contribute.</em></p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[A case study in heaptrack]]></title>
|
||
<link>https://speice.io/2018/10/case-study-optimization</link>
|
||
<guid>https://speice.io/2018/10/case-study-optimization</guid>
|
||
<pubDate>Mon, 08 Oct 2018 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[I remember early in my career someone joking that:]]></description>
|
||
<content:encoded><![CDATA[<p>I remember early in my career someone joking that:</p>
|
||
<blockquote>
|
||
<p>Programmers have it too easy these days. They should learn to develop in low memory environments
|
||
and be more efficient.</p>
|
||
</blockquote>
|
||
<p>...though it's not like the first code I wrote was for a
|
||
<a href="https://web.archive.org/web/20180924060530/https://education.ti.com/en/products/calculators/graphing-calculators/ti-84-plus-se" target="_blank" rel="noopener noreferrer">graphing calculator</a>
|
||
packing a whole 24KB of RAM.</p>
|
||
<p>But the principle remains: be efficient with the resources you have, because
|
||
<a href="http://exo-blog.blogspot.com/2007/09/what-intel-giveth-microsoft-taketh-away.html" target="_blank" rel="noopener noreferrer">what Intel giveth, Microsoft taketh away</a>.</p>
|
||
<p>My professional work is focused on this kind of efficiency; low-latency financial markets demand
|
||
that you understand at a deep level <em>exactly</em> what your code is doing. As I continue experimenting
|
||
with Rust for personal projects, it's exciting to bring a utilitarian mindset with me: there's
|
||
flexibility for the times I pretend to have a garbage collector, and flexibility for the times that
|
||
I really care about how memory is used.</p>
|
||
<p>This post is a (small) case study in how I went from the former to the latter. And ultimately, it's
|
||
intended to be a starting toolkit to empower analysis of your own code.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="curiosity">Curiosity<a href="https://speice.io/2018/10/case-study-optimization#curiosity" class="hash-link" aria-label="Direct link to Curiosity" title="Direct link to Curiosity"></a></h2>
|
||
<p>When I first started building the <a href="https://crates.io/crates/dtparse" target="_blank" rel="noopener noreferrer">dtparse</a> crate, my intention was to mirror as closely as possible
|
||
the equivalent <a href="https://github.com/dateutil/dateutil" target="_blank" rel="noopener noreferrer">Python library</a>. Python, as you may know, is garbage collected. Very
|
||
rarely is memory usage considered in Python, and I likewise wasn't paying too much attention when
|
||
<code>dtparse</code> was first being built.</p>
|
||
<p>This lackadaisical approach to memory works well enough, and I'm not planning on making <code>dtparse</code>
|
||
hyper-efficient. But every so often, I've wondered: "what exactly is going on in memory?" With the
|
||
advent of Rust 1.28 and the
|
||
<a href="https://doc.rust-lang.org/std/alloc/trait.GlobalAlloc.html" target="_blank" rel="noopener noreferrer">Global Allocator trait</a>, I had a really
|
||
great idea: <em>build a custom allocator that allows you to track your own allocations.</em> That way, you
|
||
can do things like writing tests for both correct results and correct memory usage. I gave it a
|
||
<a href="https://crates.io/crates/qadapt" target="_blank" rel="noopener noreferrer">shot</a>, but learned very quickly: <strong>never write your own allocator</strong>. It went from "fun
|
||
weekend project" to "I have literally no idea what my computer is doing" at breakneck speed.</p>
|
||
<p>Instead, I'll highlight a separate path I took to make sense of my memory usage: <a href="https://github.com/KDE/heaptrack" target="_blank" rel="noopener noreferrer">heaptrack</a>.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="turning-on-the-system-allocator">Turning on the System Allocator<a href="https://speice.io/2018/10/case-study-optimization#turning-on-the-system-allocator" class="hash-link" aria-label="Direct link to Turning on the System Allocator" title="Direct link to Turning on the System Allocator"></a></h2>
|
||
<p>This is the hardest part of the post. Because Rust uses
|
||
<a href="https://github.com/rust-lang/rust/pull/27400#issue-41256384" target="_blank" rel="noopener noreferrer">its own allocator</a> by default,
|
||
<code>heaptrack</code> is unable to properly record unmodified Rust code. To remedy this, we'll make use of the
|
||
<code>#[global_allocator]</code> attribute.</p>
|
||
<p>Specifically, in <code>lib.rs</code> or <code>main.rs</code>, add this:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">use</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">alloc</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">System</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token attribute attr-name" style="color:hsl(35, 99%, 36%)">#[global_allocator]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token constant" style="color:hsl(35, 99%, 36%)">GLOBAL</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">System</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">System</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>...and that's it. Everything else comes essentially for free.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="running-heaptrack">Running heaptrack<a href="https://speice.io/2018/10/case-study-optimization#running-heaptrack" class="hash-link" aria-label="Direct link to Running heaptrack" title="Direct link to Running heaptrack"></a></h2>
|
||
<p>Assuming you've installed heaptrack <small>(Homebrew in Mac, package manager
|
||
in Linux, ??? in Windows)</small>, all that's left is to fire up your application:</p>
|
||
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">heaptrack my_application</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>It's that easy. After the program finishes, you'll see a file in your local directory with a name
|
||
like <code>heaptrack.my_appplication.XXXX.gz</code>. If you load that up in <code>heaptrack_gui</code>, you'll see
|
||
something like this:</p>
|
||
<p><img decoding="async" loading="lazy" alt="heaptrack" src="https://speice.io/assets/images/heaptrack-before-11fba190f97831448cc539ebb32fa579.png" width="1312" height="320" class="img_ev3q"></p>
|
||
<hr>
|
||
<p>And even these pretty colors:</p>
|
||
<p><img decoding="async" loading="lazy" alt="pretty colors" src="https://speice.io/assets/images/heaptrack-flamegraph-5094664fa79faaf2664b38505c15ac1f.png" width="1284" height="715" class="img_ev3q"></p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="reading-flamegraphs">Reading Flamegraphs<a href="https://speice.io/2018/10/case-study-optimization#reading-flamegraphs" class="hash-link" aria-label="Direct link to Reading Flamegraphs" title="Direct link to Reading Flamegraphs"></a></h2>
|
||
<p>To make sense of our memory usage, we're going to focus on that last picture - it's called a
|
||
<a href="http://www.brendangregg.com/flamegraphs.html" target="_blank" rel="noopener noreferrer">"flamegraph"</a>. These charts are typically used to
|
||
show how much time your program spends executing each function, but they're used here to show how
|
||
much memory was allocated during those functions instead.</p>
|
||
<p>For example, we can see that all executions happened during the <code>main</code> function:</p>
|
||
<p><img decoding="async" loading="lazy" alt="allocations in main" src="https://speice.io/assets/images/heaptrack-main-colorized-cfe5d7d345d32cfc1a0f297580619718.png" width="654" height="343" class="img_ev3q"></p>
|
||
<p>...and within that, all allocations happened during <code>dtparse::parse</code>:</p>
|
||
<p><img decoding="async" loading="lazy" alt="allocations in dtparse" src="https://speice.io/assets/images/heaptrack-dtparse-colorized-e6caf224f50df2dd56981f5b02970325.png" width="654" height="315" class="img_ev3q"></p>
|
||
<p>...and within <em>that</em>, allocations happened in two different places:</p>
|
||
<p><img decoding="async" loading="lazy" alt="allocations in parseinfo" src="https://speice.io/assets/images/heaptrack-parseinfo-colorized-a1898beaf28a3997ac86810f872539b7.png" width="654" height="372" class="img_ev3q"></p>
|
||
<p>Now I apologize that it's hard to see, but there's one area specifically that stuck out as an issue:
|
||
<strong>what the heck is the <code>Default</code> thing doing?</strong></p>
|
||
<p><img decoding="async" loading="lazy" alt="pretty colors" src="https://speice.io/assets/images/heaptrack-flamegraph-default-26cc411d387f58f50cb548f8e81df1a1.png" width="1284" height="715" class="img_ev3q"></p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="optimizing-dtparse">Optimizing dtparse<a href="https://speice.io/2018/10/case-study-optimization#optimizing-dtparse" class="hash-link" aria-label="Direct link to Optimizing dtparse" title="Direct link to Optimizing dtparse"></a></h2>
|
||
<p>See, I knew that there were some allocations during calls to <code>dtparse::parse</code>, but I was totally
|
||
wrong about where the bulk of allocations occurred in my program. Let me post the code and see if
|
||
you can spot the mistake:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)">/// Main entry point for using `dtparse`.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">parse</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">timestr</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">str</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">ParseResult</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">NaiveDateTime</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Option</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">FixedOffset</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> res </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Parser</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">default</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">parse</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> timestr</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">None</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">None</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token boolean" style="color:hsl(35, 99%, 36%)">false</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token boolean" style="color:hsl(35, 99%, 36%)">false</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">None</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token boolean" style="color:hsl(35, 99%, 36%)">false</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">HashMap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token operator" style="color:hsl(221, 87%, 60%)">?</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Ok</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">res</span><span class="token number" style="color:hsl(35, 99%, 36%)">.0</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> res</span><span class="token number" style="color:hsl(35, 99%, 36%)">.1</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<blockquote>
|
||
<p><a href="https://github.com/bspeice/dtparse/blob/4d7c5dd99572823fa4a390b483c38ab020a2172f/src/lib.rs#L1286" target="_blank" rel="noopener noreferrer">dtparse</a></p>
|
||
</blockquote>
|
||
<hr>
|
||
<p>Because <code>Parser::parse</code> requires a mutable reference to itself, I have to create a new
|
||
<code>Parser::default</code> every time it receives a string. This is excessive! We'd rather have an immutable
|
||
parser that can be re-used, and avoid allocating memory in the first place.</p>
|
||
<p>Armed with that information, I put some time in to
|
||
<a href="https://github.com/bspeice/dtparse/commit/741afa34517d6bc1155713bbc5d66905fea13fad#diff-b4aea3e418ccdb71239b96952d9cddb6" target="_blank" rel="noopener noreferrer">make the parser immutable</a>.
|
||
Now that I can re-use the same parser over and over, the allocations disappear:</p>
|
||
<p><img decoding="async" loading="lazy" alt="allocations cleaned up" src="https://speice.io/assets/images/heaptrack-flamegraph-after-cedc4c3519313f5af538364165e92c34.png" width="1272" height="712" class="img_ev3q"></p>
|
||
<p>In total, we went from requiring 2 MB of memory in
|
||
<a href="https://crates.io/crates/dtparse/1.0.2" target="_blank" rel="noopener noreferrer">version 1.0.2</a>:</p>
|
||
<p><img decoding="async" loading="lazy" alt="memory before" src="https://speice.io/assets/images/heaptrack-closeup-12ae3897c033ccb3684a88dd45592e14.png" width="717" height="116" class="img_ev3q"></p>
|
||
<p>All the way down to 300KB in <a href="https://crates.io/crates/dtparse/1.0.3" target="_blank" rel="noopener noreferrer">version 1.0.3</a>:</p>
|
||
<p><img decoding="async" loading="lazy" alt="memory after" src="https://speice.io/assets/images/heaptrack-closeup-after-967bc4596c480bcc9e8410b0a7a64a00.png" width="739" height="123" class="img_ev3q"></p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://speice.io/2018/10/case-study-optimization#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion"></a></h2>
|
||
<p>In the end, you don't need to write a custom allocator to be efficient with memory, great tools
|
||
already exist to help you understand what your program is doing.</p>
|
||
<p><strong>Use them.</strong></p>
|
||
<p>Given that <a href="https://en.wikipedia.org/wiki/Moore%27s_law" target="_blank" rel="noopener noreferrer">Moore's Law</a> is
|
||
<a href="https://www.technologyreview.com/s/601441/moores-law-is-dead-now-what/" target="_blank" rel="noopener noreferrer">dead</a>, we've all got to do
|
||
our part to take back what Microsoft stole.</p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[Isomorphic desktop apps with Rust]]></title>
|
||
<link>https://speice.io/2018/09/isomorphic-apps</link>
|
||
<guid>https://speice.io/2018/09/isomorphic-apps</guid>
|
||
<pubDate>Sat, 15 Sep 2018 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[I both despise Javascript and am stunned by its success doing some really cool things. It's]]></description>
|
||
<content:encoded><![CDATA[<p>I both despise Javascript and am stunned by its success doing some really cool things. It's
|
||
<a href="https://www.destroyallsoftware.com/talks/the-birth-and-death-of-javascript" target="_blank" rel="noopener noreferrer">this duality</a> that's
|
||
led me to a couple of (very) late nights over the past weeks trying to reconcile myself as I
|
||
bootstrap a simple desktop application.</p>
|
||
<p>See, as much as
|
||
<a href="https://webassembly.org/docs/faq/#is-webassembly-trying-to-replace-javascript" target="_blank" rel="noopener noreferrer">Webassembly isn't trying to replace Javascript</a>,
|
||
<strong>I want Javascript gone</strong>. There are plenty of people who don't share my views, and they are
|
||
probably nicer and more fun at parties. But I cringe every time "Webpack" is mentioned, and I think
|
||
it's hilarious that the
|
||
<a href="https://ecma-international.org/publications/standards/Ecma-402.htm" target="_blank" rel="noopener noreferrer">language specification</a>
|
||
dramatically outpaces anyone's
|
||
<a href="https://kangax.github.io/compat-table/es2016plus/" target="_blank" rel="noopener noreferrer">actual implementation</a>. The answer to this
|
||
conundrum is of course to recompile code from newer versions of the language to older versions <em>of
|
||
the same language</em> before running. At least <a href="https://babeljs.io/" target="_blank" rel="noopener noreferrer">Babel</a> is a nice tongue-in-cheek reference.</p>
|
||
<p>Yet for as much hate as <a href="https://electronjs.org/" target="_blank" rel="noopener noreferrer">Electron</a> receives, it does a stunningly good job at solving a really hard
|
||
problem: <em>how the hell do I put a button on the screen and react when the user clicks it</em>? GUI
|
||
programming is hard, straight up. But if browsers are already able to run everywhere, why don't we
|
||
take advantage of someone else solving the hard problems for us? I don't like that I have to use
|
||
Javascript for it, but I really don't feel inclined to whip out good ol' <a href="https://wxwidgets.org/" target="_blank" rel="noopener noreferrer">wxWidgets</a>.</p>
|
||
<p>Now there are other native solutions (<a href="https://github.com/LeoTindall/libui-rs/" target="_blank" rel="noopener noreferrer">libui-rs</a>, <a href="https://github.com/PistonDevelopers/conrod" target="_blank" rel="noopener noreferrer">conrod</a>, <a href="https://github.com/kenz-gelsoft/wxRust" target="_blank" rel="noopener noreferrer">oh hey wxWdidgets again!</a>), but
|
||
those also have their own issues with distribution, styling, etc. With Electron, I can
|
||
<code>yarn create electron-app my-app</code> and just get going, knowing that packaging/upgrades/etc. are built
|
||
in.</p>
|
||
<p>My question is: given recent innovations with WASM, <em>are we Electron yet</em>?</p>
|
||
<p>No, not really.</p>
|
||
<p>Instead, <strong>what would it take to get to a point where we can skip Javascript in Electron apps?</strong></p>
|
||
<p>Truth is, WASM/Webassembly is a pretty new technology and I'm a total beginner in this area. There
|
||
may already be solutions to the issues I discuss, but I'm totally unaware of them, so I'm going to
|
||
try and organize what I did manage to discover.</p>
|
||
<p>I should also mention that the content and things I'm talking about here are not intended to be
|
||
prescriptive, but more "if someone else is interested, what do we already know doesn't work?" <em>I
|
||
expect everything in this post to be obsolete within two months.</em> Even over the course of writing
|
||
this, <a href="https://mnt.io/2018/08/28/from-rust-to-beyond-the-asm-js-galaxy/" target="_blank" rel="noopener noreferrer">a separate blog post</a> had
|
||
to be modified because <a href="https://github.com/WebAssembly/binaryen/pull/1642" target="_blank" rel="noopener noreferrer">upstream changes</a> broke a
|
||
<a href="https://github.com/rustwasm/wasm-bindgen/pull/787" target="_blank" rel="noopener noreferrer">Rust tool</a> the post tried to use. The post
|
||
ultimately
|
||
<a href="https://mnt.io/2018/08/28/from-rust-to-beyond-the-asm-js-galaxy/#comment-477" target="_blank" rel="noopener noreferrer">got updated</a>, <strong>but
|
||
all this happened within the span of a week.</strong> Things are moving quickly.</p>
|
||
<p>I'll also note that we're going to skip <a href="http://asmjs.org/" target="_blank" rel="noopener noreferrer">asm.js</a> and <a href="https://kripken.github.io/emscripten-site/" target="_blank" rel="noopener noreferrer">emscripten</a>. Truth be told, I couldn't get
|
||
either of these to output anything, and so I'm just going to say
|
||
<a href="https://en.wikipedia.org/wiki/Here_be_dragons" target="_blank" rel="noopener noreferrer">here be dragons.</a> Everything I'm discussing here
|
||
uses the <code>wasm32-unknown-unknown</code> target.</p>
|
||
<p>The code that I <em>did</em> get running is available
|
||
<a href="https://github.com/speice-io/isomorphic-rust" target="_blank" rel="noopener noreferrer">over here</a>. Feel free to use it as a starting point,
|
||
but I'm mostly including the link as a reference for the things that were attempted.</p>
|
||
<h1>An Example Running Application</h1>
|
||
<p>So, I did <em>technically</em> get a running application:</p>
|
||
<p><img decoding="async" loading="lazy" alt="Electron app using WASM" src="https://speice.io/assets/images/electron-percy-wasm-9ccb2be15a9bed6da44486afc266bad5.png" width="800" height="319" class="img_ev3q"></p>
|
||
<p>...which you can also try out if you want:</p>
|
||
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">git</span><span class="token plain"> clone https://github.com/speice-io/isomorphic-rust.git</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">cd</span><span class="token plain"> isomorphic_rust/percy</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">yarn</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">install</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&&</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">yarn</span><span class="token plain"> start</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>...but I wouldn't really call it a "high quality" starting point to base future work on. It's mostly
|
||
there to prove this is possible in the first place. And that's something to be proud of! There's a
|
||
huge amount of engineering that went into showing a window with the text "It's alive!".</p>
|
||
<p>There's also a lot of usability issues that prevent me from recommending anyone try Electron and
|
||
WASM apps at the moment, and I think that's the more important thing to discuss.</p>
|
||
<h1>Issue the First: Complicated Toolchains</h1>
|
||
<p>I quickly established that <a href="https://github.com/rustwasm/wasm-bindgen" target="_blank" rel="noopener noreferrer">wasm-bindgen</a> was necessary to "link" my Rust code to Javascript. At
|
||
that point you've got an Electron app that starts an HTML page which ultimately fetches your WASM
|
||
blob. To keep things simple, the goal was to package everything using <a href="https://webpack.js.org/" target="_blank" rel="noopener noreferrer">webpack</a> so that I could just
|
||
load a <code>bundle.js</code> file on the page. That decision was to be the last thing that kinda worked in
|
||
this process.</p>
|
||
<p>The first issue
|
||
<a href="https://www.reddit.com/r/rust/comments/98lpun/unable_to_load_wasm_for_electron_application/" target="_blank" rel="noopener noreferrer">I ran into</a>
|
||
while attempting to bundle everything via <code>webpack</code> is a detail in the WASM spec:</p>
|
||
<blockquote>
|
||
<p>This function accepts a Response object, or a promise for one, and ... <strong>[if > it] does not match
|
||
the <code>application/wasm</code> MIME type</strong>, the returned promise will be rejected with a TypeError;</p>
|
||
<p><a href="https://webassembly.org/docs/web/#additional-web-embedding-api" target="_blank" rel="noopener noreferrer">WebAssembly - Additional Web Embedding API</a></p>
|
||
</blockquote>
|
||
<p>Specifically, if you try and load a WASM blob without the MIME type set, you'll get an error. On the
|
||
web this isn't a huge issue, as the server can set MIME types when delivering the blob. With
|
||
Electron, you're resolving things with a <code>file://</code> URL and thus can't control the MIME type:</p>
|
||
<p><img decoding="async" loading="lazy" alt="TypeError: Incorrect response MIME type. Expected &#39;application/wasm&#39;." src="https://speice.io/assets/images/incorrect-MIME-type-a977835e8dcbfdb20fdda3c67ee4f76c.png" width="795" height="301" class="img_ev3q"></p>
|
||
<p>There are a couple of solutions depending on how far into the deep end you care to venture:</p>
|
||
<ul>
|
||
<li>Embed a static file server in your Electron application</li>
|
||
<li>Use a <a href="https://electronjs.org/docs/api/protocol" target="_blank" rel="noopener noreferrer">custom protocol</a> and custom protocol handler</li>
|
||
<li>Host your WASM blob on a website that you resolve at runtime</li>
|
||
</ul>
|
||
<p>But all these are pretty bad solutions and defeat the purpose of using WASM in the first place.
|
||
Instead, my workaround was to
|
||
<a href="https://github.com/webpack/webpack/issues/7918" target="_blank" rel="noopener noreferrer">open a PR with <code>webpack</code></a> and use regex to remove
|
||
calls to <code>instantiateStreaming</code> in the
|
||
<a href="https://github.com/speice-io/isomorphic-rust/blob/master/percy/build.sh#L21-L25" target="_blank" rel="noopener noreferrer">build script</a>:</p>
|
||
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">cargo</span><span class="token plain"> +nightly build </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">wasm32-unknown-unknown </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&&</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> wasm-bindgen </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$WASM_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/debug/</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$WASM_NAME</span><span class="token string" style="color:hsl(119, 34%, 47%)">.wasm"</span><span class="token plain"> --out-dir </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$APP_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token plain"> --no-typescript </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&&</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Have to use --mode=development so we can patch out the call to instantiateStreaming</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/node_modules/webpack-cli/bin/cli.js"</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--mode</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">development </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$APP_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/app_loader.js"</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$APP_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/bundle.js"</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&&</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">sed</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-i</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'s/.*instantiateStreaming.*//g'</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$APP_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/bundle.js"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>Once that lands, the
|
||
<a href="https://github.com/speice-io/isomorphic-rust/blob/master/percy_patched_webpack/build.sh#L24-L27" target="_blank" rel="noopener noreferrer">build process</a>
|
||
becomes much simpler:</p>
|
||
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">cargo</span><span class="token plain"> +nightly build </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--target</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">wasm32-unknown-unknown </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&&</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> wasm-bindgen </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$WASM_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/debug/</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$WASM_NAME</span><span class="token string" style="color:hsl(119, 34%, 47%)">.wasm"</span><span class="token plain"> --out-dir </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$APP_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token plain"> --no-typescript </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&&</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">\</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/node_modules/webpack-cli/bin/cli.js"</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--mode</span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain">production </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$APP_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/app_loader.js"</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-o</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"</span><span class="token string variable" style="color:hsl(221, 87%, 60%)">$APP_DIR</span><span class="token string" style="color:hsl(119, 34%, 47%)">/bundle.js"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>But we're not done yet! After we compile Rust into WASM and link WASM to Javascript (via
|
||
<code>wasm-bindgen</code> and <code>webpack</code>), we still have to make an Electron app. For this purpose I used a
|
||
starter app from <a href="https://electronforge.io/" target="_blank" rel="noopener noreferrer">Electron Forge</a>, and then a
|
||
<a href="https://github.com/speice-io/isomorphic-rust/blob/master/percy/package.json#L8" target="_blank" rel="noopener noreferrer"><code>prestart</code> script</a>
|
||
to actually handle starting the application.</p>
|
||
<p>The
|
||
<a href="https://github.com/speice-io/isomorphic-rust/blob/master/percy/package.json#L8" target="_blank" rel="noopener noreferrer">final toolchain</a>
|
||
looks something like this:</p>
|
||
<ul>
|
||
<li><code>yarn start</code> triggers the <code>prestart</code> script</li>
|
||
<li><code>prestart</code> checks for missing tools (<code>wasm-bindgen-cli</code>, etc.) and then:<!-- -->
|
||
<ul>
|
||
<li>Uses <code>cargo</code> to compile the Rust code into WASM</li>
|
||
<li>Uses <code>wasm-bindgen</code> to link the WASM blob into a Javascript file with exported symbols</li>
|
||
<li>Uses <code>webpack</code> to bundle the page start script with the Javascript we just generated<!-- -->
|
||
<ul>
|
||
<li>Uses <code>babel</code> under the hood to compile the <code>wasm-bindgen</code> code down from ES6 into something
|
||
browser-compatible</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
<li>The <code>start</code> script runs an Electron Forge handler to do some sanity checks</li>
|
||
<li>Electron actually starts</li>
|
||
</ul>
|
||
<p>...which is complicated. I think more work needs to be done to either build a high-quality starter
|
||
app that can manage these steps, or another tool that "just handles" the complexity of linking a
|
||
compiled WASM file into something the Electron browser can run.</p>
|
||
<h1>Issue the Second: WASM tools in Rust</h1>
|
||
<p>For as much as I didn't enjoy the Javascript tooling needed to interface with Rust, the Rust-only
|
||
bits aren't any better at the moment. I get it, a lot of projects are just starting off, and that
|
||
leads to a fragmented ecosystem. Here's what I can recommend as a starting point:</p>
|
||
<p>Don't check in your <code>Cargo.lock</code> files to version control. If there's a disagreement between the
|
||
version of <code>wasm-bindgen-cli</code> you have installed and the <code>wasm-bindgen</code> you're compiling with in
|
||
<code>Cargo.lock</code>, you get a nasty error:</p>
|
||
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">it looks like the Rust project used to create this wasm file was linked against</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">a different version of wasm-bindgen than this binary:</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">rust wasm file: 0.2.21</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> this binary: 0.2.17</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Currently the bindgen format is unstable enough that these two version must</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">exactly match, so it's required that these two version are kept in sync by</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">either updating the wasm-bindgen dependency or this binary.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>Not that I ever managed to run into this myself (<em>coughs nervously</em>).</p>
|
||
<p>There are two projects attempting to be "application frameworks": <a href="https://chinedufn.github.io/percy/" target="_blank" rel="noopener noreferrer">percy</a> and <a href="https://github.com/DenisKolodin/yew" target="_blank" rel="noopener noreferrer">yew</a>. Between those,
|
||
I managed to get <a href="https://github.com/speice-io/isomorphic-rust/tree/master/percy" target="_blank" rel="noopener noreferrer">two</a>
|
||
<a href="https://github.com/speice-io/isomorphic-rust/tree/master/percy_patched_webpack" target="_blank" rel="noopener noreferrer">examples</a> running
|
||
using <code>percy</code>, but was unable to get an
|
||
<a href="https://github.com/speice-io/isomorphic-rust/tree/master/yew" target="_blank" rel="noopener noreferrer">example</a> running with <code>yew</code> because
|
||
of issues with "missing modules" during the <code>webpack</code> step:</p>
|
||
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">ERROR </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">in</span><span class="token plain"> ./dist/electron_yew_wasm_bg.wasm</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Module not found: Error: Can</span><span class="token string" style="color:hsl(119, 34%, 47%)">'t resolve '</span><span class="token function" style="color:hsl(221, 87%, 60%)">env</span><span class="token string" style="color:hsl(119, 34%, 47%)">' in '</span><span class="token plain">/home/bspeice/Development/isomorphic_rust/yew/dist'</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> @ ./dist/electron_yew_wasm_bg.wasm</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> @ ./dist/electron_yew_wasm.js</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> @ ./dist/app.js</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> @ ./dist/app_loader.js</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>If you want to work with the browser APIs directly, your choices are <a href="https://crates.io/crates/percy-webapis" target="_blank" rel="noopener noreferrer">percy-webapis</a> or <a href="https://crates.io/crates/stdweb" target="_blank" rel="noopener noreferrer">stdweb</a> (or
|
||
eventually <a href="https://crates.io/crates/web-sys" target="_blank" rel="noopener noreferrer">web-sys</a>). See above for my <code>percy</code> examples, but when I tried
|
||
<a href="https://github.com/speice-io/isomorphic-rust/tree/master/stdweb" target="_blank" rel="noopener noreferrer">an example with <code>stdweb</code></a>, I was
|
||
unable to get it running:</p>
|
||
<div class="language-sh codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-sh codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">ERROR </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">in</span><span class="token plain"> ./dist/stdweb_electron_bg.wasm</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Module not found: Error: Can</span><span class="token string" style="color:hsl(119, 34%, 47%)">'t resolve '</span><span class="token function" style="color:hsl(221, 87%, 60%)">env</span><span class="token string" style="color:hsl(119, 34%, 47%)">' in '</span><span class="token plain">/home/bspeice/Development/isomorphic_rust/stdweb/dist'</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> @ ./dist/stdweb_electron_bg.wasm</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> @ ./dist/stdweb_electron.js</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> @ ./dist/app_loader.js</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>At this point I'm pretty convinced that <code>stdweb</code> is causing issues for <code>yew</code> as well, but can't
|
||
prove it.</p>
|
||
<p>I did also get a <a href="https://github.com/speice-io/isomorphic-rust/tree/master/minimal" target="_blank" rel="noopener noreferrer">minimal example</a>
|
||
running that doesn't depend on any tools besides <code>wasm-bindgen</code>. However, it requires manually
|
||
writing "<code>extern C</code>" blocks for everything you need from the browser. Es no bueno.</p>
|
||
<p>Finally, from a tools and platform view, there are two up-and-coming packages that should be
|
||
mentioned: <a href="https://crates.io/crates/js-sys" target="_blank" rel="noopener noreferrer">js-sys</a> and <a href="https://crates.io/crates/web-sys" target="_blank" rel="noopener noreferrer">web-sys</a>. Their purpose is to be fundamental building blocks that exposes
|
||
the browser's APIs to Rust. If you're interested in building an app framework from scratch, these
|
||
should give you the most flexibility. I didn't touch either in my research, though I expect them to
|
||
be essential long-term.</p>
|
||
<p>So there's a lot in play from the Rust side of things, and it's just going to take some time to
|
||
figure out what works and what doesn't.</p>
|
||
<h1>Issue the Third: Known Unknowns</h1>
|
||
<p>Alright, so after I managed to get an application started, I stopped there. It was a good deal of
|
||
effort to chain together even a proof of concept, and at this point I'd rather learn <a href="https://www.typescriptlang.org/" target="_blank" rel="noopener noreferrer">Typescript</a>
|
||
than keep trying to maintain an incredibly brittle pipeline. Blasphemy, I know...</p>
|
||
<p>The important point I want to make is that there's a lot unknown about how any of this holds up
|
||
outside proofs of concept. Things I didn't attempt:</p>
|
||
<ul>
|
||
<li>Testing</li>
|
||
<li>Packaging</li>
|
||
<li>Updates</li>
|
||
<li>Literally anything related to why I wanted to use Electron in the first place</li>
|
||
</ul>
|
||
<h1>What it Would Take</h1>
|
||
<p>Much as I don't like Javascript, the tools are too shaky for me to recommend mixing Electron and
|
||
WASM at the moment. There's a lot of innovation happening, so who knows? Someone might have an
|
||
application in production a couple months from now. But at the moment, I'm personally going to stay
|
||
away.</p>
|
||
<p>Let's finish with a wishlist then - here are the things that I think need to happen before
|
||
Electron/WASM/Rust can become a thing:</p>
|
||
<ul>
|
||
<li>Webpack still needs some updates. The necessary work is in progress, but hasn't landed yet
|
||
(<a href="https://github.com/webpack/webpack/pull/7983" target="_blank" rel="noopener noreferrer">#7983</a>)</li>
|
||
<li>Browser API libraries (<code>web-sys</code> and <code>stdweb</code>) need to make sure they can support running in
|
||
Electron (see module error above)</li>
|
||
<li>Projects need to stabilize. There's talk of <code>stdweb</code> being turned into a Rust API
|
||
<a href="https://github.com/rustwasm/team/issues/226#issuecomment-418475778" target="_blank" rel="noopener noreferrer">on top of web-sys</a>, and percy
|
||
<a href="https://github.com/chinedufn/percy/issues/24" target="_blank" rel="noopener noreferrer">moving to web-sys</a>, both of which are big changes</li>
|
||
<li><code>wasm-bindgen</code> is great, but still in the "move fast and break things" phase</li>
|
||
<li>A good "boilerplate" app would dramatically simplify the start-up costs;
|
||
<a href="https://github.com/chentsulin/electron-react-boilerplate" target="_blank" rel="noopener noreferrer">electron-react-boilerplate</a> comes to
|
||
mind as a good project to imitate</li>
|
||
<li>More blog posts/contributors! I think Electron + Rust could be cool, but I have no idea what I'm
|
||
doing</li>
|
||
</ul>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[Primitives in Rust are weird (and cool)]]></title>
|
||
<link>https://speice.io/2018/09/primitives-in-rust-are-weird</link>
|
||
<guid>https://speice.io/2018/09/primitives-in-rust-are-weird</guid>
|
||
<pubDate>Sat, 01 Sep 2018 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[I wrote a really small Rust program a while back because I was curious. I was 100% convinced it]]></description>
|
||
<content:encoded><![CDATA[<p>I wrote a really small Rust program a while back because I was curious. I was 100% convinced it
|
||
couldn't possibly run:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">println!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"{}"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">to_string</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>And to my complete befuddlement, it compiled, ran, and produced a completely sensible output.</p>
|
||
<p>The reason I was so surprised has to do with how Rust treats a special category of things I'm going to
|
||
call <em>primitives</em>. In the current version of the Rust book, you'll see them referred to as
|
||
<a href="https://doc.rust-lang.org/book/second-edition/ch03-02-data-types.html#scalar-types" target="_blank" rel="noopener noreferrer">scalars</a>, and in older versions they'll be called <a href="https://doc.rust-lang.org/book/first-edition/primitive-types.html" target="_blank" rel="noopener noreferrer">primitives</a>, but
|
||
we're going to stick with the name <em>primitive</em> for the time being. Explaining why this program is so
|
||
cool requires talking about a number of other programming languages, and keeping a consistent
|
||
terminology makes things easier.</p>
|
||
<p><strong>You've been warned:</strong> this is going to be a tedious post about a relatively minor issue that
|
||
involves Java, Python, C, and x86 Assembly. And also me pretending like I know what I'm talking
|
||
about with assembly.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="defining-primitives-java">Defining primitives (Java)<a href="https://speice.io/2018/09/primitives-in-rust-are-weird#defining-primitives-java" class="hash-link" aria-label="Direct link to Defining primitives (Java)" title="Direct link to Defining primitives (Java)"></a></h2>
|
||
<p>The reason I'm using the name <em>primitive</em> comes from how much of my life is Java right now. For the most part I like Java, but I digress. In Java, there's a special
|
||
name for some specific types of values:</p>
|
||
<blockquote>
|
||
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">bool char byte</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">short int long</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">float double</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
</blockquote>
|
||
<p>They are referred to as <a href="https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html" target="_blank" rel="noopener noreferrer">primitives</a>. And relative to the other bits of Java,
|
||
they have two unique features. First, they don't have to worry about the
|
||
<a href="https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions" target="_blank" rel="noopener noreferrer">billion-dollar mistake</a>;
|
||
primitives in Java can never be <code>null</code>. Second: <em>they can't have instance methods</em>.
|
||
Remember that Rust program from earlier? Java has no idea what to do with it:</p>
|
||
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">class</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Main</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">public</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">void</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">String</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"> args</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">int</span><span class="token plain"> x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">System</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">println</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">toString</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Triggers a compiler error</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>The error is:</p>
|
||
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">Main.java:5: error: int cannot be dereferenced</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> System.out.println(x.toString());</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> ^</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">1 error</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>Specifically, Java's <a href="https://docs.oracle.com/javase/10/docs/api/java/lang/Object.html" target="_blank" rel="noopener noreferrer"><code>Object</code></a>
|
||
and things that inherit from it are pointers under the hood, and we have to dereference them before
|
||
the fields and methods they define can be used. In contrast, <em>primitive types are just values</em> -
|
||
there's nothing to be dereferenced. In memory, they're just a sequence of bits.</p>
|
||
<p>If we really want, we can turn the <code>int</code> into an
|
||
<a href="https://docs.oracle.com/javase/10/docs/api/java/lang/Integer.html" target="_blank" rel="noopener noreferrer"><code>Integer</code></a> and then dereference
|
||
it, but it's a bit wasteful:</p>
|
||
<div class="language-java codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-java codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">class</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Main</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">public</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">static</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">void</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">String</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"> args</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">int</span><span class="token plain"> x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Integer</span><span class="token plain"> y </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Integer</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">valueOf</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">System</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">out</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">println</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">toString</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>This creates the variable <code>y</code> of type <code>Integer</code> (which inherits <code>Object</code>), and at run time we
|
||
dereference <code>y</code> to locate the <code>toString()</code> function and call it. Rust obviously handles things a bit
|
||
differently, but we have to dig into the low-level details to see it in action.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="low-level-handling-of-primitives-c">Low Level Handling of Primitives (C)<a href="https://speice.io/2018/09/primitives-in-rust-are-weird#low-level-handling-of-primitives-c" class="hash-link" aria-label="Direct link to Low Level Handling of Primitives (C)" title="Direct link to Low Level Handling of Primitives (C)"></a></h2>
|
||
<p>We first need to build a foundation for reading and understanding the assembly code the final answer
|
||
requires. Let's begin with showing how the <code>C</code> language (and your computer) thinks about "primitive"
|
||
values in memory:</p>
|
||
<div class="language-c codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-c codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">void</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">my_function</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">int</span><span class="token plain"> num</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">int</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">int</span><span class="token plain"> x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">my_function</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>The <a href="https://godbolt.org/z/lgNYcc" target="_blank" rel="noopener noreferrer">compiler explorer</a> gives us an easy way of showing off the
|
||
assembly-level code that's generated: <small>whose output has been lightly
|
||
edited</small></p>
|
||
<div class="language-nasm codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-nasm codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token label function" style="color:hsl(221, 87%, 60%)">main:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> push </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rbp</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> mov </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rbp</span><span class="token plain">, </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rsp</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> sub </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rsp</span><span class="token plain">, </span><span class="token number" style="color:hsl(35, 99%, 36%)">16</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">; We assign the value `8` to `x` here</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> mov DWORD PTR </span><span class="token operator" style="color:hsl(221, 87%, 60%)">[</span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rbp</span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token number" style="color:hsl(35, 99%, 36%)">4</span><span class="token operator" style="color:hsl(221, 87%, 60%)">]</span><span class="token plain">, </span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">; And copy the bits making up `x` to a location</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">; `my_function` can access (`edi`)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> mov </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">eax</span><span class="token plain">, DWORD PTR </span><span class="token operator" style="color:hsl(221, 87%, 60%)">[</span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rbp</span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token number" style="color:hsl(35, 99%, 36%)">4</span><span class="token operator" style="color:hsl(221, 87%, 60%)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> mov </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">edi</span><span class="token plain">, </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">eax</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">; Call `my_function` and give it control</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> call my_function</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> mov </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">eax</span><span class="token plain">, </span><span class="token number" style="color:hsl(35, 99%, 36%)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> leave</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> ret</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token label function" style="color:hsl(221, 87%, 60%)">my_function:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> push </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rbp</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> mov </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rbp</span><span class="token plain">, </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rsp</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">; Copy the bits out of the pre-determined location (`edi`)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">; to somewhere we can use</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> mov DWORD PTR </span><span class="token operator" style="color:hsl(221, 87%, 60%)">[</span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rbp</span><span class="token operator" style="color:hsl(221, 87%, 60%)">-</span><span class="token number" style="color:hsl(35, 99%, 36%)">4</span><span class="token operator" style="color:hsl(221, 87%, 60%)">]</span><span class="token plain">, </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">edi</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> nop</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> pop </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rbp</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> ret</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>At a really low level of memory, we're copying bits around using the <a href="http://www.cs.virginia.edu/~evans/cs216/guides/x86.html" target="_blank" rel="noopener noreferrer"><code>mov</code></a> instruction;
|
||
nothing crazy. But to show how similar Rust is, let's take a look at our program translated from C
|
||
to Rust:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">my_function</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">i32</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">my_function</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>And the assembly generated when we stick it in the
|
||
<a href="https://godbolt.org/z/cAlmk0" target="_blank" rel="noopener noreferrer">compiler explorer</a>: <small>again, lightly
|
||
edited</small></p>
|
||
<div class="language-nasm codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-nasm codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token label function" style="color:hsl(221, 87%, 60%)">example:</span><span class="token plain">:main:</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> push </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rax</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">; Look familiar? We're copying bits to a location for `my_function`</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">; The compiler just optimizes out holding `x` in memory</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> mov </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">edi</span><span class="token plain">, </span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">; Call `my_function` and give it control</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> call example::my_function</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> pop </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rax</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> ret</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token label function" style="color:hsl(221, 87%, 60%)">example:</span><span class="token plain">:my_function:</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> sub </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rsp</span><span class="token plain">, </span><span class="token number" style="color:hsl(35, 99%, 36%)">4</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">; And copying those bits again, just like in C</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> mov dword ptr </span><span class="token operator" style="color:hsl(221, 87%, 60%)">[</span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rsp</span><span class="token operator" style="color:hsl(221, 87%, 60%)">]</span><span class="token plain">, </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">edi</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> add </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rsp</span><span class="token plain">, </span><span class="token number" style="color:hsl(35, 99%, 36%)">4</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> ret</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>The generated Rust assembly is functionally pretty close to the C assembly: <em>When working with
|
||
primitives, we're just dealing with bits in memory</em>.</p>
|
||
<p>In Java we have to dereference a pointer to call its functions; in Rust, there's no pointer to
|
||
dereference. So what exactly is going on with this <code>.to_string()</code> function call?</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="impl-primitive-and-python">impl primitive (and Python)<a href="https://speice.io/2018/09/primitives-in-rust-are-weird#impl-primitive-and-python" class="hash-link" aria-label="Direct link to impl primitive (and Python)" title="Direct link to impl primitive (and Python)"></a></h2>
|
||
<p>Now it's time to <strike>reveal my trap card</strike> show the revelation that tied all this
|
||
together: <em>Rust has implementations for its primitive types.</em> That's right, <code>impl</code> blocks aren't
|
||
only for <code>structs</code> and <code>traits</code>, primitives get them too. Don't believe me? Check out
|
||
<a href="https://doc.rust-lang.org/std/primitive.u32.html" target="_blank" rel="noopener noreferrer">u32</a>,
|
||
<a href="https://doc.rust-lang.org/std/primitive.f64.html" target="_blank" rel="noopener noreferrer">f64</a> and
|
||
<a href="https://doc.rust-lang.org/std/primitive.char.html" target="_blank" rel="noopener noreferrer">char</a> as examples.</p>
|
||
<p>But the really interesting bit is how Rust turns those <code>impl</code> blocks into assembly. Let's break out
|
||
the <a href="https://godbolt.org/z/6LBEwq" target="_blank" rel="noopener noreferrer">compiler explorer</a> once again:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">to_string</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>And the interesting bits in the assembly: <small>heavily trimmed down</small></p>
|
||
<div class="language-nasm codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-nasm codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token label function" style="color:hsl(221, 87%, 60%)">example:</span><span class="token plain">:main:</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> sub </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rsp</span><span class="token plain">, </span><span class="token number" style="color:hsl(35, 99%, 36%)">24</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> mov </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rdi</span><span class="token plain">, </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rsp</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> lea </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rax</span><span class="token plain">, </span><span class="token operator" style="color:hsl(221, 87%, 60%)">[</span><span class="token plain">rip </span><span class="token operator" style="color:hsl(221, 87%, 60%)">+</span><span class="token plain"> .Lbyte_str.u</span><span class="token operator" style="color:hsl(221, 87%, 60%)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> mov </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rsi</span><span class="token plain">, </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rax</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">; Cool stuff right here</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> call </span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token plain">T as alloc::string::ToString</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain">::to_string@PLT</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> mov </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rdi</span><span class="token plain">, </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rsp</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> call core::ptr::drop_in_place</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> add </span><span class="token register variable" style="color:hsl(221, 87%, 60%)">rsp</span><span class="token plain">, </span><span class="token number" style="color:hsl(35, 99%, 36%)">24</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> ret</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>Now, this assembly is a bit more complicated, but here's the big revelation: <strong>we're calling
|
||
<code>to_string()</code> as a function that exists all on its own, and giving it the instance of <code>8</code></strong>. Instead
|
||
of thinking of the value 8 as an instance of <code>u32</code> and then peeking in to find the location of the
|
||
function we want to call (like Java), we have a function that exists outside of the instance and
|
||
just give that function the value <code>8</code>.</p>
|
||
<p>This is an incredibly technical detail, but the interesting idea I had was this: <em>if <code>to_string()</code>
|
||
is a static function, can I refer to the unbound function and give it an instance?</em></p>
|
||
<p>Better explained in code (and a <a href="https://godbolt.org/z/fJY-gA" target="_blank" rel="noopener noreferrer">compiler explorer</a> link because I
|
||
seriously love this thing):</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">struct</span><span class="token plain"> </span><span class="token type-definition class-name" style="color:hsl(35, 99%, 36%)">MyVal</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">u32</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">impl</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyVal</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">to_string</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">-></span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">String</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">to_string</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> my_val </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyVal</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// THESE ARE THE SAME</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> my_val</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">to_string</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyVal</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">to_string</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">my_val</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>Rust is totally fine "binding" the function call to the instance, and also as a static.</p>
|
||
<p>MIND == BLOWN.</p>
|
||
<p>Python does the same thing where I can both call functions bound to their instances and also call as
|
||
an unbound function where I give it the instance:</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">class</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">MyClass</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">24</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">def</span><span class="token plain"> </span><span class="token function" style="color:hsl(221, 87%, 60%)">my_function</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">print</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">self</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">m </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> MyClass</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">m</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">my_function</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">MyClass</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">my_function</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">m</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>And Python tries to make you <em>think</em> that primitives can have instance methods...</p>
|
||
<div class="language-python codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-python codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token operator" style="color:hsl(221, 87%, 60%)">>></span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token builtin" style="color:hsl(119, 34%, 47%)">dir</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">[</span><span class="token string" style="color:hsl(119, 34%, 47%)">'__abs__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__add__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__and__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__class__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__cmp__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__coerce__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token string" style="color:hsl(119, 34%, 47%)">'__delattr__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__div__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__divmod__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__doc__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__float__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__floordiv__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token string" style="color:hsl(119, 34%, 47%)">'__setattr__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__sizeof__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__str__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__sub__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__subclasshook__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">'__truediv__'</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token operator" style="color:hsl(221, 87%, 60%)">>></span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># Theoretically `8.__str__()` should exist, but:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token operator" style="color:hsl(221, 87%, 60%)">>></span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">__str__</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> File </span><span class="token string" style="color:hsl(119, 34%, 47%)">"<stdin>"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> line </span><span class="token number" style="color:hsl(35, 99%, 36%)">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">__str__</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">^</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">SyntaxError</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> invalid syntax</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token operator" style="color:hsl(221, 87%, 60%)">>></span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)"># It will run if we assign it first though:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token operator" style="color:hsl(221, 87%, 60%)">>></span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> x </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">8</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token operator" style="color:hsl(221, 87%, 60%)">>></span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token plain">__str__</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token string" style="color:hsl(119, 34%, 47%)">'8'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>...but in practice it's a bit complicated.</p>
|
||
<p>So while Python handles binding instance methods in a way similar to Rust, it's still not able to
|
||
run the example we started with.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://speice.io/2018/09/primitives-in-rust-are-weird#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion"></a></h2>
|
||
<p>This was a super-roundabout way of demonstrating it, but the way Rust handles incredibly minor
|
||
details like primitives leads to really cool effects. Primitives are optimized like C in how they
|
||
have a space-efficient memory layout, yet the language still has a lot of features I enjoy in Python
|
||
(like both instance and late binding).</p>
|
||
<p>And when you put it together, there are areas where Rust does cool things nobody else can; as a
|
||
quirky feature of Rust's type system, <code>8.to_string()</code> is actually valid code.</p>
|
||
<p>Now go forth and fool your friends into thinking you know assembly. This is all I've got.</p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[What I learned porting dateutil to Rust]]></title>
|
||
<link>https://speice.io/2018/06/dateutil-parser-to-rust</link>
|
||
<guid>https://speice.io/2018/06/dateutil-parser-to-rust</guid>
|
||
<pubDate>Mon, 25 Jun 2018 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[I've mostly been a lurker in Rust for a while, making a couple small contributions here and there.]]></description>
|
||
<content:encoded><![CDATA[<p>I've mostly been a lurker in Rust for a while, making a couple small contributions here and there.
|
||
So launching <a href="https://github.com/bspeice/dtparse" target="_blank" rel="noopener noreferrer">dtparse</a> feels like nice step towards becoming a
|
||
functioning member of society. But not too much, because then you know people start asking you to
|
||
pay bills, and ain't nobody got time for that.</p>
|
||
<p>But I built dtparse, and you can read about my thoughts on the process. Or don't. I won't tell you
|
||
what to do with your life (but you should totally keep reading).</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="slow-down-what">Slow down, what?<a href="https://speice.io/2018/06/dateutil-parser-to-rust#slow-down-what" class="hash-link" aria-label="Direct link to Slow down, what?" title="Direct link to Slow down, what?"></a></h2>
|
||
<p>OK, fine, I guess I should start with <em>why</em> someone would do this.</p>
|
||
<p><a href="https://github.com/dateutil/dateutil" target="_blank" rel="noopener noreferrer">Dateutil</a> is a Python library for handling dates. The
|
||
standard library support for time in Python is kinda dope, but there are a lot of extras that go
|
||
into making it useful beyond just the <a href="https://docs.python.org/3.6/library/datetime.html" target="_blank" rel="noopener noreferrer">datetime</a>
|
||
module. <code>dateutil.parser</code> specifically is code to take all the super-weird time formats people come
|
||
up with and turn them into something actually useful.</p>
|
||
<p>Date/time parsing, it turns out, is just like everything else involving
|
||
<a href="https://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time" target="_blank" rel="noopener noreferrer">computers</a> and
|
||
<a href="https://infiniteundo.com/post/25509354022/more-falsehoods-programmers-believe-about-time" target="_blank" rel="noopener noreferrer">time</a>: it
|
||
feels like it shouldn't be that difficult to do, until you try to do it, and you realize that people
|
||
suck and this is why
|
||
<a href="https://zachholman.com/talk/utc-is-enough-for-everyone-right" target="_blank" rel="noopener noreferrer">we can't we have nice things</a>. But
|
||
alas, we'll try and make contemporary art out of the rubble and give it a pretentious name like
|
||
<em>Time</em>.</p>
|
||
<p><img decoding="async" loading="lazy" alt="A gravel mound" src="https://speice.io/assets/images/gravel-mound-4afad8bdb1cd6b0e40dd2fd41adca36f.jpg" width="800" height="374" class="img_ev3q"></p>
|
||
<blockquote>
|
||
<p><a href="https://www.goodfreephotos.com/united-states/montana/elkhorn/remains-of-the-mining-operation-elkhorn.jpg.php" target="_blank" rel="noopener noreferrer">Time</a></p>
|
||
</blockquote>
|
||
<p>What makes <code>dateutil.parser</code> great is that there's single function with a single argument that
|
||
drives what programmers interact with:
|
||
<a href="https://github.com/dateutil/dateutil/blob/6dde5d6298cfb81a4c594a38439462799ed2aef2/dateutil/parser/_parser.py#L1258" target="_blank" rel="noopener noreferrer"><code>parse(timestr)</code></a>.
|
||
It takes in the time as a string, and gives you back a reasonable "look, this is the best anyone can
|
||
possibly do to make sense of your input" value. It doesn't expect much of you.</p>
|
||
<p><a href="https://github.com/bspeice/dtparse/blob/7d565d3a78876dbebd9711c9720364fe9eba7915/src/lib.rs#L1332" target="_blank" rel="noopener noreferrer">And now it's in Rust.</a></p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="lost-in-translation">Lost in Translation<a href="https://speice.io/2018/06/dateutil-parser-to-rust#lost-in-translation" class="hash-link" aria-label="Direct link to Lost in Translation" title="Direct link to Lost in Translation"></a></h2>
|
||
<p>Having worked at a bulge-bracket bank watching Java programmers try to be Python programmers, I'm
|
||
admittedly hesitant to publish Python code that's trying to be Rust. Interestingly, Rust code can
|
||
actually do a great job of mimicking Python. It's certainly not idiomatic Rust, but I've had better
|
||
experiences than
|
||
<a href="https://webcache.googleusercontent.com/search?q=cache:wkYMpktJtnUJ:https://jackstouffer.com/blog/porting_dateutil.html+&cd=3&hl=en&ct=clnk&gl=us" target="_blank" rel="noopener noreferrer">this guy</a>
|
||
who attempted the same thing for D. These are the actual take-aways:</p>
|
||
<p>When transcribing code, <strong>stay as close to the original library as possible</strong>. I'm talking about
|
||
using the same variable names, same access patterns, the whole shebang. It's way too easy to make a
|
||
couple of typos, and all of a sudden your code blows up in new and exciting ways. Having a reference
|
||
manual for verbatim what your code should be means that you don't spend that long debugging
|
||
complicated logic, you're more looking for typos.</p>
|
||
<p>Also, <strong>don't use nice Rust things like enums</strong>. While
|
||
<a href="https://github.com/bspeice/dtparse/blob/7d565d3a78876dbebd9711c9720364fe9eba7915/src/lib.rs#L88-L94" target="_blank" rel="noopener noreferrer">one time it worked out OK for me</a>,
|
||
I also managed to shoot myself in the foot a couple times because <code>dateutil</code> stores AM/PM as a
|
||
boolean and I mixed up which was true, and which was false (side note: AM is false, PM is true). In
|
||
general, writing nice code <em>should not be a first-pass priority</em> when you're just trying to recreate
|
||
the same functionality.</p>
|
||
<p><strong>Exceptions are a pain.</strong> Make peace with it. Python code is just allowed to skip stack frames. So
|
||
when a co-worker told me "Rust is getting try-catch syntax" I properly freaked out. Turns out
|
||
<a href="https://github.com/rust-lang/rfcs/pull/243" target="_blank" rel="noopener noreferrer">he's not quite right</a>, and I'm OK with that. And while
|
||
<code>dateutil</code> is pretty well-behaved about not skipping multiple stack frames,
|
||
<a href="https://github.com/dateutil/dateutil/blob/16561fc99361979e88cccbd135393b06b1af7e90/dateutil/parser/_parser.py#L730-L865" target="_blank" rel="noopener noreferrer">130-line try-catch blocks</a>
|
||
take a while to verify.</p>
|
||
<p>As another Python quirk, <strong>be very careful about
|
||
<a href="https://github.com/dateutil/dateutil/blob/16561fc99361979e88cccbd135393b06b1af7e90/dateutil/parser/_parser.py#L494-L568" target="_blank" rel="noopener noreferrer">long nested if-elif-else blocks</a></strong>.
|
||
I used to think that Python's whitespace was just there to get you to format your code correctly. I
|
||
think that no longer. It's way too easy to close a block too early and have incredibly weird issues
|
||
in the logic. Make sure you use an editor that displays indentation levels so you can keep things
|
||
straight.</p>
|
||
<p><strong>Rust macros are not free.</strong> I originally had the
|
||
<a href="https://github.com/bspeice/dtparse/blob/b0e737f088eca8e83ab4244c6621a2797d247697/tests/compat.rs#L63-L217" target="_blank" rel="noopener noreferrer">main test body</a>
|
||
wrapped up in a macro using <a href="https://github.com/PyO3/PyO3" target="_blank" rel="noopener noreferrer">pyo3</a>. It took two minutes to compile.
|
||
After
|
||
<a href="https://github.com/bspeice/dtparse/blob/e017018295c670e4b6c6ee1cfff00dbb233db47d/tests/compat.rs#L76-L205" target="_blank" rel="noopener noreferrer">moving things to a function</a>
|
||
compile times dropped down to ~5 seconds. Turns out 150 lines * 100 tests = a lot of redundant code
|
||
to be compiled. My new rule of thumb is that any macros longer than 10-15 lines are actually
|
||
functions that need to be liberated, man.</p>
|
||
<p>Finally, <strong>I really miss list comprehensions and dictionary comprehensions.</strong> As a quick comparison,
|
||
see
|
||
<a href="https://github.com/dateutil/dateutil/blob/16561fc99361979e88cccbd135393b06b1af7e90/dateutil/parser/_parser.py#L476" target="_blank" rel="noopener noreferrer">this dateutil code</a>
|
||
and
|
||
<a href="https://github.com/bspeice/dtparse/blob/7d565d3a78876dbebd9711c9720364fe9eba7915/src/lib.rs#L619-L629" target="_blank" rel="noopener noreferrer">the implementation in Rust</a>.
|
||
I probably wrote it wrong, and I'm sorry. Ultimately though, I hope that these comprehensions can be
|
||
added through macros or syntax extensions. Either way, they're expressive, save typing, and are
|
||
super-readable. Let's get more of that.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="using-a-young-language">Using a young language<a href="https://speice.io/2018/06/dateutil-parser-to-rust#using-a-young-language" class="hash-link" aria-label="Direct link to Using a young language" title="Direct link to Using a young language"></a></h2>
|
||
<p>Now, Rust is exciting and new, which means that there's opportunity to make a substantive impact. On
|
||
more than one occasion though, I've had issues navigating the Rust ecosystem.</p>
|
||
<p>What I'll call the "canonical library" is still being built. In Python, if you need datetime
|
||
parsing, you use <code>dateutil</code>. If you want <code>decimal</code> types, it's already in the
|
||
<a href="https://docs.python.org/3.6/library/decimal.html" target="_blank" rel="noopener noreferrer">standard library</a>. While I might've gotten away
|
||
with <code>f64</code>, <code>dateutil</code> uses decimals, and I wanted to follow the principle of <strong>staying as close to
|
||
the original library as possible</strong>. Thus began my quest to find a decimal library in Rust. What I
|
||
quickly found was summarized in a comment:</p>
|
||
<blockquote>
|
||
<p>Writing a BigDecimal is easy. Writing a <em>good</em> BigDecimal is hard.</p>
|
||
<p><a href="https://github.com/rust-lang/rust/issues/8937#issuecomment-34582794" target="_blank" rel="noopener noreferrer">-cmr</a></p>
|
||
</blockquote>
|
||
<p>In practice, this means that there are at least <a href="https://crates.io/crates/bigdecimal" target="_blank" rel="noopener noreferrer">4</a>
|
||
<a href="https://crates.io/crates/rust_decimal" target="_blank" rel="noopener noreferrer">different</a>
|
||
<a href="https://crates.io/crates/decimal" target="_blank" rel="noopener noreferrer">implementations</a> <a href="https://crates.io/crates/decimate" target="_blank" rel="noopener noreferrer">available</a>.
|
||
And that's a lot of decisions to worry about when all I'm thinking is "why can't
|
||
<a href="https://en.wikipedia.org/wiki/Calendar_reform" target="_blank" rel="noopener noreferrer">calendar reform</a> be a thing" and I'm forced to dig
|
||
through a <a href="https://github.com/rust-lang/rust/issues/8937#issuecomment-31661916" target="_blank" rel="noopener noreferrer">couple</a>
|
||
<a href="https://github.com/rust-lang/rfcs/issues/334" target="_blank" rel="noopener noreferrer">different</a>
|
||
<a href="https://github.com/rust-num/num/issues/8" target="_blank" rel="noopener noreferrer">threads</a> to figure out if the library I'm look at is dead
|
||
or just stable.</p>
|
||
<p>And even when the "canonical library" exists, there's no guarantees that it will be well-maintained.
|
||
<a href="https://github.com/chronotope/chrono" target="_blank" rel="noopener noreferrer">Chrono</a> is the <em>de facto</em> date/time library in Rust, and just
|
||
released version 0.4.4 like two days ago. Meanwhile,
|
||
<a href="https://github.com/chronotope/chrono-tz" target="_blank" rel="noopener noreferrer">chrono-tz</a> appears to be dead in the water even though
|
||
<a href="https://github.com/chronotope/chrono-tz/issues/19" target="_blank" rel="noopener noreferrer">there are people happy to help maintain it</a>. I
|
||
know relatively little about it, but it appears that most of the release process is automated;
|
||
keeping that up to date should be a no-brainer.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="trial-maintenance-policy">Trial Maintenance Policy<a href="https://speice.io/2018/06/dateutil-parser-to-rust#trial-maintenance-policy" class="hash-link" aria-label="Direct link to Trial Maintenance Policy" title="Direct link to Trial Maintenance Policy"></a></h2>
|
||
<p>Specifically given "maintenance" being an
|
||
<a href="https://www.reddit.com/r/rust/comments/48540g/thoughts_on_initiators_vs_maintainers/" target="_blank" rel="noopener noreferrer">oft-discussed</a>
|
||
issue, I'm going to try out the following policy to keep things moving on <code>dtparse</code>:</p>
|
||
<ol>
|
||
<li>
|
||
<p>Issues/PRs needing <em>maintainer</em> feedback will be updated at least weekly. I want to make sure
|
||
nobody's blocking on me.</p>
|
||
</li>
|
||
<li>
|
||
<p>To keep issues/PRs needing <em>contributor</em> feedback moving, I'm going to (kindly) ask the
|
||
contributor to check in after two weeks, and close the issue without resolution if I hear nothing
|
||
back after a month.</p>
|
||
</li>
|
||
</ol>
|
||
<p>The second point I think has the potential to be a bit controversial, so I'm happy to receive
|
||
feedback on that. And if a contributor responds with "hey, still working on it, had a kid and I'm
|
||
running on 30 seconds of sleep a night," then first: congratulations on sustaining human life. And
|
||
second: I don't mind keeping those requests going indefinitely. I just want to try and balance
|
||
keeping things moving with giving people the necessary time they need.</p>
|
||
<p>I should also note that I'm still getting some best practices in place - CONTRIBUTING and
|
||
CONTRIBUTORS files need to be added, as well as issue/PR templates. In progress. None of us are
|
||
perfect.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="roadmap-and-conclusion">Roadmap and Conclusion<a href="https://speice.io/2018/06/dateutil-parser-to-rust#roadmap-and-conclusion" class="hash-link" aria-label="Direct link to Roadmap and Conclusion" title="Direct link to Roadmap and Conclusion"></a></h2>
|
||
<p>So if I've now built a <code>dateutil</code>-compatible parser, we're done, right? Of course not! That's not
|
||
nearly ambitious enough.</p>
|
||
<p>Ultimately, I'd love to have a library that's capable of parsing everything the Linux <code>date</code> command
|
||
can do (and not <code>date</code> on OSX, because seriously, BSD coreutils are the worst). I know Rust has a
|
||
coreutils rewrite going on, and <code>dtparse</code> would potentially be an interesting candidate since it
|
||
doesn't bring in a lot of extra dependencies. <a href="https://crates.io/crates/humantime" target="_blank" rel="noopener noreferrer"><code>humantime</code></a>
|
||
could help pick up some of the (current) slack in dtparse, so maybe we can share and care with each
|
||
other?</p>
|
||
<p>All in all, I'm mostly hoping that nobody's already done this and I haven't spent a bit over a month
|
||
on redundant code. So if it exists, tell me. I need to know, but be nice about it, because I'm going
|
||
to take it hard.</p>
|
||
<p>And in the mean time, I'm looking forward to building more. Onwards.</p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[Hello!]]></title>
|
||
<link>https://speice.io/2018/05/hello</link>
|
||
<guid>https://speice.io/2018/05/hello</guid>
|
||
<pubDate>Mon, 28 May 2018 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[I'll do what I can to keep this short, there's plenty of other things we both should be doing right]]></description>
|
||
<content:encoded><![CDATA[<p>I'll do what I can to keep this short, there's plenty of other things we both should be doing right
|
||
now.</p>
|
||
<p>If you're here for the bread pics, and to marvel in some other culinary side projects, I've got you
|
||
covered:</p>
|
||
<p><img decoding="async" loading="lazy" alt="Saturday Bread" src="https://speice.io/assets/images/bread-52bb152a7c29148e837d94bdf1755e1c.jpg" width="3036" height="2729" class="img_ev3q"></p>
|
||
<p>And no, I'm not posting pictures of earlier attempts that ended up turning into rocks in the oven.</p>
|
||
<p>Okay, just one:</p>
|
||
<p><img decoding="async" loading="lazy" alt="Bread as rock" src="https://speice.io/assets/images/rocks-6b9a0c44bf45210d496e2ebe2f896e0c.jpg" width="3036" height="2380" class="img_ev3q"></p>
|
||
<p>Thanks, and keep it amazing.</p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[Captain's Cookbook: Practical usage]]></title>
|
||
<link>https://speice.io/2018/01/captains-cookbook-part-2</link>
|
||
<guid>https://speice.io/2018/01/captains-cookbook-part-2</guid>
|
||
<pubDate>Tue, 16 Jan 2018 13:00:00 GMT</pubDate>
|
||
<description><![CDATA[A look at more practical usages of Cap'N Proto]]></description>
|
||
<content:encoded><![CDATA[<p>A look at more practical usages of Cap'N Proto</p>
|
||
<p><a href="https://speice.io/2018/01/captains-cookbook-part-1">Part 1</a> of this series took a look at a basic starting project
|
||
with Cap'N Proto. In this section, we're going to take the (admittedly basic) schema and look at how we can add a pretty
|
||
basic feature - sending Cap'N Proto messages between threads. It's nothing complex, but I want to make sure that there's
|
||
some documentation surrounding practical usage of the library.</p>
|
||
<p>As a quick refresher, we build a Cap'N Proto message and go through the serialization/deserialization steps
|
||
<a href="https://github.com/bspeice/capnp_cookbook_1/blob/master/src/main.rs" target="_blank" rel="noopener noreferrer">here</a>. Our current example is going to build on
|
||
the code we wrote there; after the deserialization step, we'll try and send the <code>point_reader</code> to a separate thread
|
||
for verification.</p>
|
||
<p>I'm going to walk through the attempts as I made them and my thinking throughout.
|
||
If you want to skip to the final project, check out the code available <a href="https://github.com/bspeice/capnp_cookbook_2" target="_blank" rel="noopener noreferrer">here</a></p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="attempt-1-move-the-reference">Attempt 1: Move the reference<a href="https://speice.io/2018/01/captains-cookbook-part-2#attempt-1-move-the-reference" class="hash-link" aria-label="Direct link to Attempt 1: Move the reference" title="Direct link to Attempt 1: Move the reference"></a></h2>
|
||
<p>As a first attempt, we're going to try and let Rust move the reference. Our code will look something like:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// ...assume that we own a `buffer: Vec<u8>` containing the binary message content from</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// somewhere else</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> deserialized </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token namespace">capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">serialize</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">read_message</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> buffer</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">as_slice</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token namespace">capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">message</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">ReaderOptions</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">unwrap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> point_reader </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> deserialized</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">get_root</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token namespace">point_capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">point</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Reader</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">unwrap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// By using `point_reader` inside the new thread, we're hoping that Rust can</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// safely move the reference and invalidate the original thread's usage.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Since the original thread doesn't use `point_reader` again, this should</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// be safe, right?</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> handle </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token plain">thread</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token function" style="color:hsl(221, 87%, 60%)">spawn</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">move</span><span class="token plain"> </span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">assert_eq!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">point_reader</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">get_x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">12</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">assert_eq!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">point_reader</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">get_y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">14</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> handle</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">unwrap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>Well, the Rust compiler doesn't really like this. We get four distinct errors back:</p>
|
||
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]` </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> --> src/main.rs:31:18 </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">31 | let handle = std::thread::spawn(move || { </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">error[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]` </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> --> src/main.rs:31:18 </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">31 | let handle = std::thread::spawn(move || { </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">error[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> --> src/main.rs:31:18 </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">31 | let handle = std::thread::spawn(move || { </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">error[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>: std::marker::Send` is not satisfied in `[closure@src/main.rs:31:37: 36:6 point_reader:point_capnp::point::Reader<'_>]` </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> --> src/main.rs:31:18 </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">31 | let handle = std::thread::spawn(move || { </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>` cannot be sent between threads safely </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">error: aborting due to 4 previous errors</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>Note, I've removed the help text for brevity, but suffice to say that these errors are intimidating.
|
||
Pay attention to the text that keeps on getting repeated though: <code>XYZ cannot be sent between threads safely</code>.</p>
|
||
<p>This is a bit frustrating: we own the <code>buffer</code> from which all the content was derived, and we don't have any
|
||
unsafe accesses in our code. We guarantee that we wait for the child thread to stop first, so there's no possibility
|
||
of the pointer becoming invalid because the original thread exits before the child thread does. So why is Rust
|
||
preventing us from doing something that really should be legal?</p>
|
||
<p>This is what is known as <a href="https://doc.rust-lang.org/1.8.0/book/references-and-borrowing.html" target="_blank" rel="noopener noreferrer">fighting the borrow checker</a>.
|
||
Let our crusade begin.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="attempt-2-put-the-reader-in-a-box">Attempt 2: Put the <code>Reader</code> in a <code>Box</code><a href="https://speice.io/2018/01/captains-cookbook-part-2#attempt-2-put-the-reader-in-a-box" class="hash-link" aria-label="Direct link to attempt-2-put-the-reader-in-a-box" title="Direct link to attempt-2-put-the-reader-in-a-box"></a></h2>
|
||
<p>The <a href="https://doc.rust-lang.org/std/boxed/struct.Box.html" target="_blank" rel="noopener noreferrer"><code>Box</code></a> type allows us to convert a pointer we have
|
||
(in our case the <code>point_reader</code>) into an "owned" value, which should be easier to send across threads.
|
||
Our next attempt looks something like this:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// ...assume that we own a `buffer: Vec<u8>` containing the binary message content</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// from somewhere else</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> deserialized </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token namespace">capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">serialize</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">read_message</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> buffer</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">as_slice</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token namespace">capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">message</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">ReaderOptions</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">unwrap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> point_reader </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> deserialized</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">get_root</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token namespace">point_capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">point</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Reader</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">unwrap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> boxed_reader </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Box</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">point_reader</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Now that the reader is `Box`ed, we've proven ownership, and Rust can</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// move the ownership to the new thread, right?</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> handle </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">thread</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">spawn</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">move</span><span class="token plain"> </span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">assert_eq!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">boxed_reader</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">get_x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">12</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">assert_eq!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">boxed_reader</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">get_y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">14</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> handle</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">unwrap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>Spoiler alert: still doesn't work. Same errors still show up.</p>
|
||
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">error[E0277]: the trait bound `*const u8: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>` </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> --> src/main.rs:33:18 </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">33 | let handle = std::thread::spawn(move || { </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | ^^^^^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">error[E0277]: the trait bound `*const capnp::private::layout::WirePointer: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>` </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> --> src/main.rs:33:18 </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">33 | let handle = std::thread::spawn(move || { </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | ^^^^^^^^^^^^^^^^^^ `*const capnp::private::layout::WirePointer` cannot be sent between threads safely </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">error[E0277]: the trait bound `capnp::private::arena::ReaderArena: std::marker::Sync` is not satisfied </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> --> src/main.rs:33:18 </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">33 | let handle = std::thread::spawn(move || { </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | ^^^^^^^^^^^^^^^^^^ `capnp::private::arena::ReaderArena` cannot be shared between threads safely </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">error[E0277]: the trait bound `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>: std::marker::Send` is not satisfied in `point_capnp::point::Reader<'_>` </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> --> src/main.rs:33:18 </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">33 | let handle = std::thread::spawn(move || { </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | ^^^^^^^^^^^^^^^^^^ `*const std::vec::Vec<std::option::Option<std::boxed::Box<capnp::private::capability::ClientHook + 'static>>>` cannot be sent between threads safely </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> | </span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">error: aborting due to 4 previous errors</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>Let's be a little bit smarter about the exceptions this time though. What is that
|
||
<a href="https://doc.rust-lang.org/std/marker/trait.Send.html" target="_blank" rel="noopener noreferrer"><code>std::marker::Send</code></a> thing the compiler keeps telling us about?</p>
|
||
<p>The documentation is pretty clear; <code>Send</code> is used to denote:</p>
|
||
<blockquote>
|
||
<p>Types that can be transferred across thread boundaries.</p>
|
||
</blockquote>
|
||
<p>In our case, we are seeing the error messages for two reasons:</p>
|
||
<ol>
|
||
<li>
|
||
<p>Pointers (<code>*const u8</code>) are not safe to send across thread boundaries. While we're nice in our code
|
||
making sure that we wait on the child thread to finish before closing down, the Rust compiler can't make
|
||
that assumption, and so complains that we're not using this in a safe manner.</p>
|
||
</li>
|
||
<li>
|
||
<p>The <code>point_capnp::point::Reader</code> type is itself not safe to send across threads because it doesn't
|
||
implement the <code>Send</code> trait. Which is to say, the things that make up a <code>Reader</code> are themselves not thread-safe,
|
||
so the <code>Reader</code> is also not thread-safe.</p>
|
||
</li>
|
||
</ol>
|
||
<p>So, how are we to actually transfer a parsed Cap'N Proto message between threads?</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="attempt-3-the-typedreader">Attempt 3: The <code>TypedReader</code><a href="https://speice.io/2018/01/captains-cookbook-part-2#attempt-3-the-typedreader" class="hash-link" aria-label="Direct link to attempt-3-the-typedreader" title="Direct link to attempt-3-the-typedreader"></a></h2>
|
||
<p>The <code>TypedReader</code> is a new API implemented in the Cap'N Proto <a href="https://crates.io/crates/capnp/0.8.14" target="_blank" rel="noopener noreferrer">Rust code</a>.
|
||
We're interested in it here for two reasons:</p>
|
||
<ol>
|
||
<li>
|
||
<p>It allows us to define an object where the <em>object</em> owns the underlying data. In previous attempts,
|
||
the current context owned the data, but the <code>Reader</code> itself had no such control.</p>
|
||
</li>
|
||
<li>
|
||
<p>We can compose the <code>TypedReader</code> using objects that are safe to <code>Send</code> across threads, guaranteeing
|
||
that we can transfer parsed messages across threads.</p>
|
||
</li>
|
||
</ol>
|
||
<p>The actual type info for the <a href="https://github.com/capnproto/capnproto-rust/blob/f0efc35d7e9bd8f97ca4fdeb7c57fd7ea348e303/src/message.rs#L181" target="_blank" rel="noopener noreferrer"><code>TypedReader</code></a>
|
||
is a bit complex. And to be honest, I'm still really not sure what the whole point of the
|
||
<a href="https://doc.rust-lang.org/std/marker/struct.PhantomData.html" target="_blank" rel="noopener noreferrer"><code>PhantomData</code></a> thing is either.
|
||
My impression is that it lets us enforce type safety when we know what the underlying Cap'N Proto
|
||
message represents. That is, technically the only thing we're storing is the untyped binary message;
|
||
<code>PhantomData</code> just enforces the principle that the binary represents some specific object that has been parsed.</p>
|
||
<p>Either way, we can carefully construct something which is safe to move between threads:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// ...assume that we own a `buffer: Vec<u8>` containing the binary message content from somewhere else</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> deserialized </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token namespace">capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">serialize</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">read_message</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> buffer</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">as_slice</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token namespace">capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">message</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">ReaderOptions</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">unwrap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> point_reader</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">:</span><span class="token plain"> </span><span class="token namespace">capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">message</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">TypedReader</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token namespace">capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">serialize</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">OwnedSegments</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token namespace">point_capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">point</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Owned</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token namespace">capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">message</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">TypedReader</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">deserialized</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Because the point_reader is now working with OwnedSegments (which are owned vectors) and an Owned message</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// (which is 'static lifetime), this is now safe</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> handle </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token namespace">std</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">thread</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">spawn</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">move</span><span class="token plain"> </span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token closure-params closure-punctuation punctuation" style="color:hsl(119, 34%, 47%)">|</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// The point_reader owns its data, and we use .get() to retrieve the actual point_capnp::point::Reader</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// object from it</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> point_root </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> point_reader</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">get</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">unwrap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">assert_eq!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">point_root</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">get_x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">12</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">assert_eq!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">point_root</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">get_y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">14</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> handle</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">join</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">unwrap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>And while we've left Rust to do the dirty work of actually moving the <code>point_reader</code> into the new thread,
|
||
we could also use things like <a href="https://doc.rust-lang.org/std/sync/mpsc/index.html" target="_blank" rel="noopener noreferrer"><code>mpsc</code> channels</a> to achieve a similar effect.</p>
|
||
<p>So now we're able to define basic Cap'N Proto messages, and send them all around our programs.</p>]]></content:encoded>
|
||
</item>
|
||
<item>
|
||
<title><![CDATA[Captain's Cookbook: Project setup]]></title>
|
||
<link>https://speice.io/2018/01/captains-cookbook-part-1</link>
|
||
<guid>https://speice.io/2018/01/captains-cookbook-part-1</guid>
|
||
<pubDate>Tue, 16 Jan 2018 12:00:00 GMT</pubDate>
|
||
<description><![CDATA[A basic introduction to getting started with Cap'N Proto.]]></description>
|
||
<content:encoded><![CDATA[<p>A basic introduction to getting started with Cap'N Proto.</p>
|
||
<p>I've been working a lot with <a href="https://capnproto.org/" target="_blank" rel="noopener noreferrer">Cap'N Proto</a> recently with Rust, but there's a real dearth of information
|
||
on how to set up and get going quickly. In the interest of trying to get more people using this (because I think it's
|
||
fantastic), I'm going to work through a couple of examples detailing what exactly should be done to get going.</p>
|
||
<p>So, what is Cap'N Proto? It's a data serialization library. It has contemporaries with <a href="https://developers.google.com/protocol-buffers/" target="_blank" rel="noopener noreferrer">Protobuf</a>
|
||
and <a href="https://google.github.io/flatbuffers/" target="_blank" rel="noopener noreferrer">FlatBuffers</a>, but is better compared with FlatBuffers. The whole point behind it
|
||
is to define a schema language and serialization format such that:</p>
|
||
<ol>
|
||
<li>Applications that do not share the same base programming language can communicate</li>
|
||
<li>The data and schema you use can naturally evolve over time as your needs change</li>
|
||
</ol>
|
||
<p>Accompanying this are typically code generators that take the schemas you define for your application and give you back
|
||
code for different languages to get data to and from that schema.</p>
|
||
<p>Now, what makes Cap'N Proto different from, say, Protobuf, is that there is no serialization/deserialization step the same way
|
||
as is implemented with Protobuf. Instead, the idea is that the message itself can be loaded in memory and used directly there.</p>
|
||
<p>We're going to take a look at a series of progressively more complex projects that use Cap'N Proto in an effort to provide some
|
||
examples of what idiomatic usage looks like, and shorten the startup time needed to make use of this library in Rust projects.
|
||
If you want to follow along, feel free. If not, I've posted <a href="https://github.com/bspeice/capnp_cookbook_1" target="_blank" rel="noopener noreferrer">the final result</a>
|
||
for reference.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-1-installing-capnp">Step 1: Installing <code>capnp</code><a href="https://speice.io/2018/01/captains-cookbook-part-1#step-1-installing-capnp" class="hash-link" aria-label="Direct link to step-1-installing-capnp" title="Direct link to step-1-installing-capnp"></a></h2>
|
||
<p>The <code>capnp</code> binary itself is needed for taking the schema files you write and turning them into a format that can be used by the
|
||
code generation libraries. Don't ask me what that actually means, I just know that you need to make sure this is installed.</p>
|
||
<p>I'll refer you to <a href="https://capnproto.org/install.html" target="_blank" rel="noopener noreferrer">Cap'N Proto's installation instructions</a> here. As a quick TLDR though:</p>
|
||
<ul>
|
||
<li>Linux users will likely have a binary shipped by their package manager - On Ubuntu, <code>apt install capnproto</code> is enough</li>
|
||
<li>OS X users can use <a href="https://brew.sh/" target="_blank" rel="noopener noreferrer">Homebrew</a> as an easy install path. Just <code>brew install capnp</code></li>
|
||
<li>Windows users are a bit more complicated. If you're using <a href="https://chocolatey.org/" target="_blank" rel="noopener noreferrer">Chocolatey</a>, there's <a href="https://chocolatey.org/packages/capnproto/" target="_blank" rel="noopener noreferrer">a package</a> available. If that doesn't work however, you need to download <a href="https://capnproto.org/capnproto-c++-win32-0.6.1.zip" target="_blank" rel="noopener noreferrer">a release zip</a> and make sure that the <code>capnp.exe</code> binary is in your <code>%PATH%</code> environment variable</li>
|
||
</ul>
|
||
<p>The way you know you're done with this step is if the following command works in your shell:</p>
|
||
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">capnp </span><span class="token function" style="color:hsl(221, 87%, 60%)">id</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-2-starting-a-capn-proto-rust-project">Step 2: Starting a Cap'N Proto Rust project<a href="https://speice.io/2018/01/captains-cookbook-part-1#step-2-starting-a-capn-proto-rust-project" class="hash-link" aria-label="Direct link to Step 2: Starting a Cap'N Proto Rust project" title="Direct link to Step 2: Starting a Cap'N Proto Rust project"></a></h2>
|
||
<p>After the <code>capnp</code> binary is set up, it's time to actually create our Rust project. Nothing terribly complex here, just a simple</p>
|
||
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token function" style="color:hsl(221, 87%, 60%)">mkdir</span><span class="token plain"> capnp_cookbook_1</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">cd</span><span class="token plain"> capnp_cookbook_1</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">cargo</span><span class="token plain"> init </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">--bin</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>We'll put the following content into <code>Cargo.toml</code>:</p>
|
||
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[package]</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">name = "capnp_cookbook_1"</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">version = "0.1.0"</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">authors = ["Bradlee Speice <bspeice@kcg.com>"]</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[build-dependencies]</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">capnpc = "0.8" # 1</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">[dependencies]</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">capnp = "0.8" # 2</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>This sets up:</p>
|
||
<ol>
|
||
<li>The Rust code generator (CAPNProto Compiler)</li>
|
||
<li>The Cap'N Proto runtime library (CAPNProto runtime)</li>
|
||
</ol>
|
||
<p>We've now got everything prepared that we need for writing a Cap'N Proto project.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-3-writing-a-basic-schema">Step 3: Writing a basic schema<a href="https://speice.io/2018/01/captains-cookbook-part-1#step-3-writing-a-basic-schema" class="hash-link" aria-label="Direct link to Step 3: Writing a basic schema" title="Direct link to Step 3: Writing a basic schema"></a></h2>
|
||
<p>We're going to start with writing a pretty trivial data schema that we can extend later. This is just intended to make sure
|
||
you get familiar with how to start from a basic project.</p>
|
||
<p>First, we're going to create a top-level directory for storing the schema files in:</p>
|
||
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># Assuming we're starting from the `capnp_cookbook_1` directory created earlier</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">mkdir</span><span class="token plain"> schema</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">cd</span><span class="token plain"> schema</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>Now, we're going to put the following content in <code>point.capnp</code>:</p>
|
||
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">@0xab555145c708dad2;</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">struct Point {</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> x @0 :Int32;</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> y @1 :Int32;</span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>Pretty easy, we've now got structure for an object we'll be able to quickly encode in a binary format.</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-4-setting-up-the-build-process">Step 4: Setting up the build process<a href="https://speice.io/2018/01/captains-cookbook-part-1#step-4-setting-up-the-build-process" class="hash-link" aria-label="Direct link to Step 4: Setting up the build process" title="Direct link to Step 4: Setting up the build process"></a></h2>
|
||
<p>Now it's time to actually set up the build process to make sure that Cap'N Proto generates the Rust code we'll eventually be using.
|
||
This is typically done through a <code>build.rs</code> file to invoke the schema compiler.</p>
|
||
<p>In the same folder as your <code>Cargo.toml</code> file, please put the following content in <code>build.rs</code>:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token keyword" style="color:hsl(301, 63%, 40%)">extern</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">crate</span><span class="token plain"> </span><span class="token module-declaration namespace">capnpc</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">capnpc</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">CompilerCommand</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">src_prefix</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"schema"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// 1</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">file</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"schema/point.capnp"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// 2</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">run</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">expect</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"compiling schema"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>This sets up the protocol compiler (<code>capnpc</code> from earlier) to compile the schema we've built so far.</p>
|
||
<ol>
|
||
<li>Because Cap'N Proto schema files can re-use types specified in other files, the <code>src_prefix()</code> tells the compiler
|
||
where to look for those extra files at.</li>
|
||
<li>We specify the schema file we're including by hand. In a much larger project, you could presumably build the <code>CompilerCommand</code>
|
||
dynamically, but we won't worry too much about that one for now.</li>
|
||
</ol>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-5-running-the-build">Step 5: Running the build<a href="https://speice.io/2018/01/captains-cookbook-part-1#step-5-running-the-build" class="hash-link" aria-label="Direct link to Step 5: Running the build" title="Direct link to Step 5: Running the build"></a></h2>
|
||
<p>If you've done everything correctly so far, you should be able to actually build the project and see the auto-generated code.
|
||
Run a <code>cargo build</code> command, and if you don't see <code>cargo</code> complaining, you're doing just fine!</p>
|
||
<p>So where exactly does the generated code go to? I think it's critically important for people to be able to see what the generated
|
||
code looks like, because you need to understand what you're actually programming against. The short answer is: the generated code lives
|
||
somewhere in the <code>target/</code> directory.</p>
|
||
<p>The long answer is that you're best off running a <code>find</code> command to get the actual file path:</p>
|
||
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)"># Assuming we're running from the capnp_cookbook_1 project folder</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token function" style="color:hsl(221, 87%, 60%)">find</span><span class="token plain"> </span><span class="token builtin class-name" style="color:hsl(35, 99%, 36%)">.</span><span class="token plain"> </span><span class="token parameter variable" style="color:hsl(221, 87%, 60%)">-name</span><span class="token plain"> point_capnp.rs</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>Alternately, if the <code>find</code> command isn't available, the path will look something like:</p>
|
||
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain">./target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>See if there are any paths in your target directory that look similar.</p>
|
||
<p>Now, the file content looks pretty nasty. I've included an example <a href="https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs" target="_blank" rel="noopener noreferrer">here</a>
|
||
if you aren't following along at home. There are a couple things I'll try and point out though so you can get an idea of how
|
||
the schema we wrote for the "Point" message is tied to the generated code.</p>
|
||
<p>First, the Cap'N Proto library splits things up into <code>Builder</code> and <code>Reader</code> structs. These are best thought of the same way
|
||
Rust separates <code>mut</code> from non-<code>mut</code> code. <code>Builder</code>s are <code>mut</code> versions of your message, and <code>Reader</code>s are immutable versions.</p>
|
||
<p>For example, the <a href="https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L90" target="_blank" rel="noopener noreferrer"><code>Builder</code> impl</a> for <code>point</code> defines <a href="https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L105" target="_blank" rel="noopener noreferrer"><code>get_x()</code></a>, <a href="https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L109" target="_blank" rel="noopener noreferrer"><code>set_x()</code></a>, <a href="https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L113" target="_blank" rel="noopener noreferrer"><code>get_y()</code></a>, and <a href="https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L117" target="_blank" rel="noopener noreferrer"><code>set_y()</code></a> methods.
|
||
In comparison, the <a href="https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L38" target="_blank" rel="noopener noreferrer"><code>Reader</code> impl</a> only defines <a href="https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L47" target="_blank" rel="noopener noreferrer"><code>get_x()</code></a> and <a href="https://github.com/bspeice/capnp_cookbook_1/blob/master/target/debug/build/capnp_cookbook_1-c6e2990393c32fe6/out/point_capnp.rs#L51" target="_blank" rel="noopener noreferrer"><code>get_y()</code></a> methods.</p>
|
||
<p>So now we know that there are some <code>get</code> and <code>set</code> methods available for our <code>x</code> and <code>y</code> coordinates;
|
||
but what do we actually do with those?</p>
|
||
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="step-6-making-a-point">Step 6: Making a point<a href="https://speice.io/2018/01/captains-cookbook-part-1#step-6-making-a-point" class="hash-link" aria-label="Direct link to Step 6: Making a point" title="Direct link to Step 6: Making a point"></a></h2>
|
||
<p>So we've install Cap'N Proto, gotten a project set up, and can generate schema code now. It's time to actually start building
|
||
Cap'N Proto messages! I'm going to put the code you need here because it's small, and put some extra long comments inline. This code
|
||
should go in <a href="https://github.com/bspeice/capnp_cookbook_1/blob/master/src/main.rs" target="_blank" rel="noopener noreferrer"><code>src/main.rs</code></a>:</p>
|
||
<div class="language-rust codeBlockContainer_Ckt0 theme-code-block" style="--prism-background-color:hsl(230, 1%, 98%);--prism-color:hsl(230, 8%, 24%)"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-rust codeBlock_bY9V thin-scrollbar" style="background-color:hsl(230, 1%, 98%);color:hsl(230, 8%, 24%)"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token comment" style="color:hsl(230, 4%, 64%)">// Note that we use `capnp` here, NOT `capnpc`</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">extern</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">crate</span><span class="token plain"> </span><span class="token module-declaration namespace">capnp</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// We create a module here to define how we are to access the code</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token comment" style="color:hsl(230, 4%, 64%)">// being included.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">pub</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mod</span><span class="token plain"> </span><span class="token module-declaration namespace">point_capnp</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// The environment variable OUT_DIR is set by Cargo, and</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// is the location of all the code that was built as part</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// of the codegen step.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// point_capnp.rs is the actual file to include</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">include!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token macro property" style="color:hsl(5, 74%, 59%)">concat!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token macro property" style="color:hsl(5, 74%, 59%)">env!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token string" style="color:hsl(119, 34%, 47%)">"OUT_DIR"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token string" style="color:hsl(119, 34%, 47%)">"/point_capnp.rs"</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token keyword" style="color:hsl(301, 63%, 40%)">fn</span><span class="token plain"> </span><span class="token function-definition function" style="color:hsl(221, 87%, 60%)">main</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// The process of building a Cap'N Proto message is a bit tedious.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// We start by creating a generic Builder; it acts as the message</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// container that we'll later be filling with content of our `Point`</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> builder </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token namespace">capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">message</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Builder</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new_default</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Because we need a mutable reference to the `builder` later,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// we fence off this part of the code to allow sequential mutable</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// borrows. As I understand it, non-lexical lifetimes:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// https://github.com/rust-lang/rust-roadmap/issues/16</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// will make this no longer necessary</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// And now we can set up the actual message we're trying to create</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> point_msg </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> builder</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">init_root</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token namespace">point_capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">point</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Builder</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Stuff our message with some content</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> point_msg</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">set_x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">12</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> point_msg</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">set_y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token number" style="color:hsl(35, 99%, 36%)">14</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// It's now time to serialize our message to binary. Let's set up a buffer for that:</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> buffer </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Vec</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// And actually fill that buffer with our data</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token namespace">capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">serialize</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">write_message</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> buffer</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token plain">builder</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">unwrap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// Finally, let's deserialize the data</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> deserialized </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> </span><span class="token namespace">capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">serialize</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">read_message</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token operator" style="color:hsl(221, 87%, 60%)">&</span><span class="token keyword" style="color:hsl(301, 63%, 40%)">mut</span><span class="token plain"> buffer</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">as_slice</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token namespace">capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">message</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">ReaderOptions</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token function" style="color:hsl(221, 87%, 60%)">new</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">unwrap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// `deserialized` is currently a generic reader; it understands</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// the content of the message we gave it (i.e. that there are two</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// int32 values) but doesn't really know what they represent (the Point).</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// This is where we map the generic data back into our schema.</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token keyword" style="color:hsl(301, 63%, 40%)">let</span><span class="token plain"> point_reader </span><span class="token operator" style="color:hsl(221, 87%, 60%)">=</span><span class="token plain"> deserialized</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">get_root</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token operator" style="color:hsl(221, 87%, 60%)"><</span><span class="token namespace">point_capnp</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token namespace">point</span><span class="token namespace punctuation" style="color:hsl(119, 34%, 47%)">::</span><span class="token class-name" style="color:hsl(35, 99%, 36%)">Reader</span><span class="token operator" style="color:hsl(221, 87%, 60%)">></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">unwrap</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token comment" style="color:hsl(230, 4%, 64%)">// We can now get our x and y values back, and make sure they match</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">assert_eq!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">point_reader</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">get_x</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">12</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"> </span><span class="token macro property" style="color:hsl(5, 74%, 59%)">assert_eq!</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token plain">point_reader</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">.</span><span class="token function" style="color:hsl(221, 87%, 60%)">get_y</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">(</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">,</span><span class="token plain"> </span><span class="token number" style="color:hsl(35, 99%, 36%)">14</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">)</span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:hsl(230, 8%, 24%)"><span class="token plain"></span><span class="token punctuation" style="color:hsl(119, 34%, 47%)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
|
||
<p>And with that, we've now got a functioning project. Here's the content I'm planning to go over next as we build up
|
||
some practical examples of Cap'N Proto in action:</p>]]></content:encoded>
|
||
</item>
|
||
</channel>
|
||
</rss> |