From 555eca26605037755cdc52512b406d6af7b2b789 Mon Sep 17 00:00:00 2001 From: Bradlee Speice Date: Wed, 26 Dec 2018 10:19:34 -0500 Subject: [PATCH] Continue drafting wor --- _drafts/understanding-allocations-in-rust.md | 77 ++++++++++++++++---- 1 file changed, 61 insertions(+), 16 deletions(-) diff --git a/_drafts/understanding-allocations-in-rust.md b/_drafts/understanding-allocations-in-rust.md index d1281cd..ab8e0a8 100644 --- a/_drafts/understanding-allocations-in-rust.md +++ b/_drafts/understanding-allocations-in-rust.md @@ -1,6 +1,6 @@ --- layout: post -title: "Understanding Allocations" +title: "Understanding Heap Allocations in Rust" description: "An introduction to the Rust memory model" category: tags: [rust] @@ -8,33 +8,72 @@ tags: [rust] 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've known what a linker was, but there's a staggering complexity to get from -[source code to `main()`](https://www.youtube.com/watch?v=dOfucXtyEsU). Rust programmers -use the [`Box`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html) type -all the time, but there's a rich history of the Rust language itself wrapped up in +I knew what a linker was, but there's a staggering complexity to get from +[from `main()` to an executable](https://www.youtube.com/watch?v=dOfucXtyEsU). +Rust programmers use the [`Box`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html) +type all the time, but there's a rich history of the Rust language itself wrapped up in [how special it is](https://manishearth.github.io/blog/2017/01/10/rust-tidbits-box-is-special/). In a similar vein, I want you to look at code and understand memory; the complex choreography of processor, operating system, and program that frees you -to focus on functionality beyond rote book-keeping. The Rust compiler relieves a great deal -of the cognitive burden associated with memory management. Even so, let's make time -to explore what's going on under the hood, so we can make better exploit the systems -involved in the code we write. +to focus on functionality far beyond frivolous book-keeping. The Rust compiler relieves +a great deal of the cognitive burden associated with memory management, but let's make time +to explore what's going on under the hood. Let's learn a bit about allocating memory in Rust. # Table of Contents This post is intended as both guide and reference material; we'll work to establish -an understanding of how Rust makes use of memory in a program, then summarize each +an understanding of the different memory types Rust makes use of, then summarize each section for easy citation in the future. To that end, a table of contents is provided to assist in easy navigation: -- [Distinguishing regions of memory](#distinguishing-regions-of-memory) -- Rust and the Stack -- Rust and the Heap -- Understanding Compiler Optimizations -- Summary: When does Rust allocate? +- [Foreword](#foreword) +- Non-Heap Memory Types +- Piling On - the Heap in Rust +- Compiler Optimizations Make Everything Complicated +- Summary: When Does Rust Allocate? +- Appendix and Further Reading + +# Foreword + +There's a simple way to guarantee you never need to know the content +of this article: + +1. Only write `#![no_std]` crates +2. Never use `unsafe` +3. Never use `#![feature(alloc)]` + +For some uses of Rust, typically embedded devices, these constraints make sense. +They're working with very limited memory, and the program binary size itself may +affect the memory available! There's no operating system able to manage the heap, +but that's not an issue because your program is likely the only one running. +The [embedonomicon] is ever in mind, and you just might interact with extra +peripherals by reading and writing to exact memory addresses. + +Most Rust programs find these requirements overly burdensome though. C++ developers +would struggle without access to [`std::vector`](https://en.cppreference.com/w/cpp/container/vector), +and Rust developers would struggle without [`std::vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html). +But in this scenario, `std::vec` is actually part of the +[`alloc` crate](https://doc.rust-lang.org/alloc/vec/struct.Vec.html), and thus off-limits. +Or how would you use trait objects? Rust's monomorphization still works, but there's no +[`Box`](https://doc.rust-lang.org/alloc/boxed/struct.Box.html) +available to use for dynamic dispatch. + +Given a target audience of "basically every Rust developer," let's talk about +some of the details you don't normally have to worry about. This article will focus +on "safe" Rust only; `unsafe` mode allows you to make use of platform-specific +allocation APIs (think [libc] and [winapi] implementations of [malloc]) that +we'll ignore for the time being. We'll also assume a "debug" build of libraries +and applications (what you get with `cargo run` and `cargo test`) and address +"release" mode at the end (`cargo run --release` and `cargo test --release`). + +Finally, a caveat: while the details are unlikely to change, the Rust docs +include a warning worth repeating here: + +> Rust does not currently have a rigorously and formally defined memory model. +> - the [Rust docs](https://doc.rust-lang.org/std/ptr/fn.read_volatile.html) # Distinguishing regions of memory @@ -61,7 +100,13 @@ Questions: 1. Where do collection types allocate memory? 2. Does a Box<> always allocate heap? 3. Passing Box vs. genericizing/monomorphization +4. Other pointer types? Do Rc<>/Arc<> force heap allocation? # Understanding compiler optimizations -Example: Compiler stripping out allocations of Box<>, Vec::push() \ No newline at end of file +Example: Compiler stripping out allocations of Box<>, Vec::push() + +[embedonomicon]: https://docs.rust-embedded.org/embedonomicon/ +[libc]: CRATES.IO LINK +[winapi]: CRATES.IO LINK +[malloc]: MANPAGE LINK \ No newline at end of file