mirror of
https://github.com/bspeice/speice.io
synced 2024-11-14 22:18:10 -05:00
122 lines
79 KiB
HTML
122 lines
79 KiB
HTML
|
<!doctype html><html lang=en dir=ltr class="blog-wrapper blog-post-page plugin-blog plugin-id-default" data-has-hydrated=false><meta charset=UTF-8><meta name=generator content="Docusaurus v3.6.0"><title data-rh=true>Allocations in Rust: Dynamic memory | The Old Speice Guy</title><meta data-rh=true name=viewport content="width=device-width,initial-scale=1.0"><meta data-rh=true name=twitter:card content=summary_large_image><meta data-rh=true property=og:url content=https://speice.io/2019/02/a-heaping-helping><meta data-rh=true property=og:locale content=en><meta data-rh=true name=docusaurus_locale content=en><meta data-rh=true name=docusaurus_tag content=default><meta data-rh=true name=docsearch:language content=en><meta data-rh=true name=docsearch:docusaurus_tag content=default><meta data-rh=true property=og:title content="Allocations in Rust: Dynamic memory | The Old Speice Guy"><meta data-rh=true name=description content="Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and"><meta data-rh=true property=og:description content="Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and"><meta data-rh=true property=og:type content=article><meta data-rh=true property=article:published_time content=2019-02-07T12:00:00.000Z><link data-rh=true rel=icon href=/img/favicon.ico><link data-rh=true rel=canonical href=https://speice.io/2019/02/a-heaping-helping><link data-rh=true rel=alternate href=https://speice.io/2019/02/a-heaping-helping hreflang=en><link data-rh=true rel=alternate href=https://speice.io/2019/02/a-heaping-helping hreflang=x-default><script data-rh=true type=application/ld+json>{"@context":"https://schema.org","@id":"https://speice.io/2019/02/a-heaping-helping","@type":"BlogPosting","author":{"@type":"Person","name":"Bradlee Speice"},"dateModified":"2024-11-10T02:05:00.000Z","datePublished":"2019-02-07T12:00:00.000Z","description":"Managing dynamic memory is hard. Some languages assume users will do it themselves (C, C++), and","headline":"Allocations in Rust: Dynamic memory","isPartOf":{"@id":"https://speice.io/","@type":"Blog","name":"Blog"},"keywords":[],"mainEntityOfPage":"https://speice.io/2019/02/a-heaping-helping","name":"Allocations in Rust: Dynamic memory","url":"https://speice.io/2019/02/a-heaping-helping"}</script><link rel=alternate type=application/rss+xml href=/rss.xml title="The Old Speice Guy RSS Feed"><link rel=alternate type=application/atom+xml href=/atom.xml title="The Old Speice Guy Atom Feed"><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css integrity=sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM crossorigin><link rel=stylesheet href=/assets/css/styles.ae6ff4a3.css><script src=/assets/js/runtime~main.751b419d.js defer></script><script src=/assets/js/main.62ce6156.js defer></script><body class=navigation-with-keyboard><script>!function(){var t,e=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme")}catch(t){}}();t=null!==e?e:"light",document.documentElement.setAttribute("data-theme",t)}(),function(){try{for(var[t,e]of new URLSearchParams(window.location.search).entries())if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id=__docusaurus><div role=region aria-label="Skip to main content"><a class=skipToContent_fXgn href=#__docusaurus_skipToContent_fallback>Skip to main content</a></div><nav aria-label=Main class="navbar navbar--fixed-top"><div class=navbar__inner><div class=navbar__items><button aria-label="Toggle navigation bar" aria-expanded=false class="navbar__toggle clean-btn" type=button><svg width=30 height=30 viewBox="0 0 30 30" aria-hidden=true><path stroke=currentColor stroke-linecap=round stroke-miterlimit=10 stroke-width=2 d="M4 7h22M4 15h22M4 23h22"/></svg></button><a class=navbar__brand href=/><div class=navbar__logo><img src=/im
|
|||
|
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"/></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 /></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>
|
|||
|
<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=#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 pla
|
|||
|
<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=#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"/></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 /></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">
|
|||
|
<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=#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=#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.</div></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Blog post page navigation"><a class="pagination-nav__link pagination-nav__link--prev" href=/2019/02/stacking-up><div class=pagination-nav__sublabel>Older post</div><div class=pagination-nav__label>Allocations in Rust: Fixed memory</div></a><a class="pagination-nav__link pagination-nav__link--next" href=/2019/02/08/compiler-optimizations><div class=pagination-nav__sublabel>Newer post</div><div class=pagination-nav__label>Allocations in Rust: Compiler optimizations</div></a></nav></main><div class="col col--2"><div class="tableOfContents_bqdL thin-scrollbar"><ul class="table-of-contents table-of-contents__left-border"><li><a href=#smart-pointers class="table-of-contents__link toc-highlight">Smart pointers</a><li><a href=#collections class="table-of-contents__link toc-highlight">Collections</a><li><a href=#heap-alternatives class="table-of-contents__link toc-highlight">Heap Alternatives</a><li><a href=#tracing-allocators class="table-of-contents__link toc-highlight">Tracing Allocators</a></ul></div></div></div></div></div><footer class=footer><div class="container container-fluid"><div class="footer__bottom text--center"><div class=footer__copyright>Copyright © 2024 Bradlee Speice</div></div></div></footer></div>
|