"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["7580"],{4935:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return a},default:function(){return d},frontMatter:function(){return i},metadata:function(){return s},toc:function(){return c}});var s=n(6583),o=n(5893),r=n(65);let i={slug:"2019/02/understanding-allocations-in-rust",title:"Allocations in Rust: Foreword",date:new Date("2019-02-04T12:00:00.000Z"),authors:["bspeice"],tags:[]},a=void 0,l={authorsImageUrls:[void 0]},c=[];function h(e){let t={a:"a",blockquote:"blockquote",code:"code",em:"em",hr:"hr",li:"li",ol:"ol",p:"p",ul:"ul",...(0,r.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(t.p,{children:["There's an alchemy of distilling complex technical topics into articles and videos that change the\nway programmers see the tools they interact with on a regular basis. I knew what a linker was, but\nthere's a staggering amount of complexity in between\n",(0,o.jsxs)(t.a,{href:"https://www.youtube.com/watch?v=dOfucXtyEsU",children:["the OS and ",(0,o.jsx)(t.code,{children:"main()"})]}),". Rust programmers use the\n",(0,o.jsx)(t.a,{href:"https://doc.rust-lang.org/stable/std/boxed/struct.Box.html",children:(0,o.jsx)(t.code,{children:"Box"})})," type all the time, but there's a\nrich history of the Rust language itself wrapped up in\n",(0,o.jsx)(t.a,{href:"https://manishearth.github.io/blog/2017/01/10/rust-tidbits-box-is-special/",children:"how special it is"}),"."]}),"\n",(0,o.jsx)(t.p,{children:"In a similar vein, this series attempts to look at code and understand how memory is used; the\ncomplex choreography of operating system, compiler, and program that frees you to focus on\nfunctionality far-flung from frivolous book-keeping. The Rust compiler relieves a great deal of the\ncognitive burden associated with memory management, but we're going to step into its world for a\nwhile."}),"\n",(0,o.jsx)(t.p,{children:"Let's learn a bit about memory in Rust."}),"\n",(0,o.jsx)(t.hr,{}),"\n",(0,o.jsxs)(t.p,{children:["Rust's three defining features of\n",(0,o.jsx)(t.a,{href:"https://www.rust-lang.org/",children:"Performance, Reliability, and Productivity"})," are all driven to a great\ndegree by the how the Rust compiler understands memory usage. Unlike managed memory languages (Java,\nPython), Rust\n",(0,o.jsx)(t.a,{href:"https://words.steveklabnik.com/borrow-checking-escape-analysis-and-the-generational-hypothesis",children:"doesn't really"}),"\ngarbage collect; instead, it uses an\n",(0,o.jsx)(t.a,{href:"https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html",children:"ownership"}),' system to reason about\nhow long objects will last in your program. In some cases, if the life of an object is fairly\ntransient, Rust can make use of a very fast region called the "stack." When that\'s not possible,\nRust uses\n',(0,o.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Memory_management#Dynamic_memory_allocation",children:"dynamic (heap) memory"}),"\nand the ownership system to ensure you can't accidentally corrupt memory. It's not as fast, but it\nis important to have available."]}),"\n",(0,o.jsx)(t.p,{children:"That said, there are specific situations in Rust where you'd never need to worry about the\nstack/heap distinction! If you:"}),"\n",(0,o.jsxs)(t.ol,{children:["\n",(0,o.jsxs)(t.li,{children:["Never use ",(0,o.jsx)(t.code,{children:"unsafe"})]}),"\n",(0,o.jsxs)(t.li,{children:["Never use ",(0,o.jsx)(t.code,{children:"#![feature(alloc)]"})," or the ",(0,o.jsxs)(t.a,{href:"https://doc.rust-lang.org/alloc/index.html",children:[(0,o.jsx)(t.code,{children:"alloc"})," crate"]})]}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:"...then it's not possible for you to use dynamic memory!"}),"\n",(0,o.jsxs)(t.p,{children:["For some uses of Rust, typically embedded devices, these constraints are OK. They have very limited\nmemory, and the program binary size itself may significantly affect what's available! There's no\noperating system able to manage this\n",(0,o.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Virtual_memory",children:'"virtual memory"'})," thing, but that's not an issue\nbecause there's only one running application. The\n",(0,o.jsx)(t.a,{href:"https://docs.rust-embedded.org/embedonomicon/preface.html",children:"embedonomicon"}),' is ever in mind, and\ninteracting with the "real world" through extra peripherals is accomplished by reading and writing\nto ',(0,o.jsx)(t.a,{href:"https://bob.cs.sonoma.edu/IntroCompOrg-RPi/sec-gpio-mem.html",children:"specific memory addresses"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["Most Rust programs find these requirements overly burdensome though. C++ developers would struggle\nwithout access to ",(0,o.jsx)(t.a,{href:"https://en.cppreference.com/w/cpp/container/vector",children:(0,o.jsx)(t.code,{children:"std::vector"})})," (except those\nhardcore no-STL people), and Rust developers would struggle without\n",(0,o.jsx)(t.a,{href:"https://doc.rust-lang.org/std/vec/struct.Vec.html",children:(0,o.jsx)(t.code,{children:"std::vec"})}),". But with the constraints above,\n",(0,o.jsx)(t.code,{children:"std::vec"})," is actually a part of the\n",(0,o.jsxs)(t.a,{href:"https://doc.rust-lang.org/alloc/vec/struct.Vec.html",children:[(0,o.jsx)(t.code,{children:"alloc"})," crate"]}),", and thus off-limits. ",(0,o.jsx)(t.code,{children:"Box"}),",\n",(0,o.jsx)(t.code,{children:"Rc"}),", etc., are also unusable for the same reason."]}),"\n",(0,o.jsxs)(t.p,{children:["Whether writing code for embedded devices or not, the important thing in both situations is how much\nyou know ",(0,o.jsx)(t.em,{children:"before your application starts"})," about what its memory usage will look like. In embedded\ndevices, there's a small, fixed amount of memory to use. In a browser, you have no idea how large\n",(0,o.jsx)(t.a,{href:"https://www.google.com",children:"google.com"}),"'s home page is until you start trying to download it. The\ncompiler uses this knowledge (or lack thereof) to optimize how memory is used; put simply, your code\nruns faster when the compiler can guarantee exactly how much memory your program needs while it's\nrunning. This series is all about understanding how the compiler reasons about your program, with an\nemphasis on the implications for performance."]}),"\n",(0,o.jsx)(t.p,{children:"Now let's address some conditions and caveats before going much further:"}),"\n",(0,o.jsxs)(t.ul,{children:["\n",(0,o.jsxs)(t.li,{children:['We\'ll focus on "safe" Rust only; ',(0,o.jsx)(t.code,{children:"unsafe"})," lets you use platform-specific allocation API's\n(",(0,o.jsx)(t.a,{href:"https://www.tutorialspoint.com/c_standard_library/c_function_malloc.htm",children:(0,o.jsx)(t.code,{children:"malloc"})}),") that we'll\nignore."]}),"\n",(0,o.jsxs)(t.li,{children:['We\'ll assume a "debug" build of Rust code (what you get with ',(0,o.jsx)(t.code,{children:"cargo run"})," and ",(0,o.jsx)(t.code,{children:"cargo test"}),") and\naddress (pun intended) release mode at the end (",(0,o.jsx)(t.code,{children:"cargo run --release"})," and ",(0,o.jsx)(t.code,{children:"cargo test --release"}),")."]}),"\n",(0,o.jsxs)(t.li,{children:["All content will be run using Rust 1.32, as that's the highest currently supported in the\n",(0,o.jsx)(t.a,{href:"https://godbolt.org/",children:"Compiler Exporer"}),". As such, we'll avoid upcoming innovations like\n",(0,o.jsxs)(t.a,{href:"https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md",children:["compile-time evaluation of ",(0,o.jsx)(t.code,{children:"static"})]}),"\nthat are available in nightly."]}),"\n",(0,o.jsxs)(t.li,{children:["Because of the nature of the content, being able to read assembly is helpful. We'll keep it\nsimple, but I ",(0,o.jsx)(t.a,{href:"https://stackoverflow.com/a/4584131/1454178",children:"found"})," a\n",(0,o.jsx)(t.a,{href:"https://stackoverflow.com/a/26026278/1454178",children:"refresher"})," on the ",(0,o.jsx)(t.code,{children:"push"})," and ",(0,o.jsx)(t.code,{children:"pop"}),"\n",(0,o.jsx)(t.a,{href:"http://www.cs.virginia.edu/~evans/cs216/guides/x86.html",children:"instructions"})," was helpful while writing\nthis."]}),"\n",(0,o.jsxs)(t.li,{children:["I've tried to be precise in saying only what I can prove using the tools (ASM, docs) that are\navailable, but if there's something said in error it will be corrected expeditiously. Please let\nme know at ",(0,o.jsx)(t.a,{href:"mailto:bradlee@speice.io",children:"bradlee@speice.io"})]}),"\n"]}),"\n",(0,o.jsx)(t.p,{children:"Finally, I'll do what I can to flag potential future changes but the Rust docs have a notice worth\nrepeating:"}),"\n",(0,o.jsxs)(t.blockquote,{children:["\n",(0,o.jsx)(t.p,{children:"Rust does not currently have a rigorously and formally defined memory model."}),"\n",(0,o.jsxs)(t.p,{children:["-- ",(0,o.jsx)(t.a,{href:"https://doc.rust-lang.org/std/ptr/fn.read_volatile.html",children:"the docs"})]}),"\n"]})]})}function d(e={}){let{wrapper:t}={...(0,r.a)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(h,{...e})}):h(e)}},65:function(e,t,n){n.d(t,{Z:function(){return a},a:function(){return i}});var s=n(7294);let o={},r=s.createContext(o);function i(e){let t=s.useContext(r);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),s.createElement(r.Provider,{value:t},e.children)}},6583:function(e){e.exports=JSON.parse('{"permalink":"/2019/02/understanding-allocations-in-rust","source":"@site/blog/2019-02-04-understanding-allocations-in-rust/index.mdx","title":"Allocations in Rust: Foreword","description":"There\'s an alchemy of distilling complex technical topics into articles and videos that change the","date":"2019-02-04T12:00:00.000Z","tags":[],"readingTime":3.785,"hasTruncateMarker":true,"authors":[{"name":"Bradlee Speice","socials":{"github":"https://github.com/bspeice"},"key":"bspeice","page":null}],"frontMatter":{"slug":"2019/02/understanding-allocations-in-rust","title":"Allocations in Rust: Foreword","date":"2019-02-04T12:00:00.000Z","authors":["bspeice"],"tags":[]},"unlisted":false,"lastUpdatedAt":1731204300000,"prevItem":{"title":"Allocations in Rust: Global memory","permalink":"/2019/02/the-whole-world"},"nextItem":{"title":"QADAPT - debug_assert! for allocations","permalink":"/2018/12/allocation-safety"}}')}}]);