mirror of
				https://github.com/bspeice/speice.io
				synced 2025-10-31 09:30:32 -04:00 
			
		
		
		
	More tweaking
This commit is contained in:
		| @ -8,17 +8,17 @@ tags: [rust] | |||||||
|  |  | ||||||
| There's an alchemy of distilling complex technical topics into articles and videos | 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. | 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 complexity to get from | I knew what a linker was, but there's a staggering amount of complexity in between | ||||||
| [from `main()` to an executable](https://www.youtube.com/watch?v=dOfucXtyEsU). | [`main()` and your executable](https://www.youtube.com/watch?v=dOfucXtyEsU). | ||||||
| Rust programmers use the [`Box`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html) | 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 | 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/). | [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; | In a similar vein, I want you to look at code and understand how memory is used; | ||||||
| the complex choreography of processor, operating system, and program that frees you | 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 | 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 let's make time | a great deal of the cognitive burden associated with memory management, but we're going | ||||||
| to explore what's going on under the hood. | to step into its world for a while. | ||||||
|  |  | ||||||
| Let's learn a bit about memory in Rust. | Let's learn a bit about memory in Rust. | ||||||
|  |  | ||||||
| @ -30,16 +30,15 @@ section for easy citation in the future. To that end, a table of contents is pro | |||||||
| to assist in easy navigation: | to assist in easy navigation: | ||||||
|  |  | ||||||
| - [Foreword](#foreword) | - [Foreword](#foreword) | ||||||
| - [Non-Heap Memory Types](#non-heap-memory-types) | - [Stacking Up: Non-Heap Memory Types](#non-heap-memory-types) | ||||||
| - [Piling On - Rust and the Heap](#piling-on-rust-and-the-heap) | - [Piling On: Rust and the Heap](#piling-on-rust-and-the-heap) | ||||||
| - [Compiler Optimizations Make Everything Complicated](#compiler-optimizations-make-everything-complicated) | - [Compiler Optimizations Make Everything Complicated](#compiler-optimizations-make-everything-complicated) | ||||||
| - Summary: When Does Rust Allocate? | - Summary: When Does Rust Allocate? | ||||||
| - [Appendix and Further Reading](#appendix-and-further-reading) | - [Appendix and Further Reading](#appendix-and-further-reading) | ||||||
|  |  | ||||||
| # Foreword | # Foreword | ||||||
|  |  | ||||||
| There's a simple way to guarantee you never need to know the content | There's a simple checklist to see if you can skip over reading this article. You must: | ||||||
| of this article: |  | ||||||
|  |  | ||||||
| 1. Only write `#![no_std]` crates | 1. Only write `#![no_std]` crates | ||||||
| 2. Never use `unsafe` | 2. Never use `unsafe` | ||||||
| @ -47,35 +46,54 @@ of this article: | |||||||
|  |  | ||||||
| For some uses of Rust, typically embedded devices, these constraints make sense. | 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 | 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, | significantly affect what's available! There's no operating system able to manage | ||||||
| but that's not an issue because your program is likely the only one running. | this "virtual memory" junk, but that's not an issue because there's only one | ||||||
| The [embedonomicon] is ever in mind, and you just might interact with extra | running application. The [embedonomicon] is ever in mind, and interacting with the | ||||||
| peripherals by reading and writing to exact memory addresses. | "real world" through extra peripherals is accomplished by reading and writing to | ||||||
|  | exact memory addresses. | ||||||
|  |  | ||||||
| Most Rust programs find these requirements overly burdensome though. C++ developers | 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), | 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). | (except those hardcore no-STL guys), and Rust developers would struggle without | ||||||
| But in this scenario, `std::vec` is actually part of the | [`std::vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html). But in this scenario, | ||||||
| [`alloc` crate](https://doc.rust-lang.org/alloc/vec/struct.Vec.html), and thus off-limits. | `std::vec` is actually part of the [`alloc` crate](https://doc.rust-lang.org/alloc/vec/struct.Vec.html), | ||||||
| Or how would you use trait objects? Rust's monomorphization still works, but there's no | and thus off-limits (because the `alloc` crate requires `#![feature(alloc)]`). | ||||||
|  | Or how would you use trait objects? There's no | ||||||
| [`Box<dyn Trait>`](https://doc.rust-lang.org/alloc/boxed/struct.Box.html) | [`Box<dyn Trait>`](https://doc.rust-lang.org/alloc/boxed/struct.Box.html) | ||||||
| available to use for dynamic dispatch. | available to use for dynamic dispatch. | ||||||
|  |  | ||||||
| Given a target audience of "basically every Rust developer," let's talk about | Whether writing code for embedded devices or not, the important thing in both situations | ||||||
| some of the details you don't normally have to worry about. This article will focus | is how much you know *before your application starts* about what your memory usage looks like. | ||||||
| on "safe" Rust only; `unsafe` mode allows you to make use of platform-specific | In the embedded device example, there's a small, fixed amount of memory you can possibly use. | ||||||
| allocation APIs (think [libc] and [winapi] implementations of [malloc]) that | In a browser, however, you have no idea how large [google.com's home page] is until you start | ||||||
| we'll ignore for the time being. We'll also assume a "debug" build of libraries | trying to download it. The compiler uses this information (or lack thereof) to optimize | ||||||
| and applications (what you get with `cargo run` and `cargo test`) and address | how memory is used; put simply, your code runs faster when the compiler can guarantee exactly | ||||||
| "release" mode at the end (`cargo run --release` and `cargo test --release`). | how much memory your program needs while it's running. This post is all about understanding | ||||||
|  | the optimization tricks the compiler uses, and how you can help the compiler and make | ||||||
|  | your programs more efficient. | ||||||
|  |  | ||||||
| Finally, a caveat: while the details are unlikely to change, the Rust docs | Now let's address some conditions and caveats before going much further. | ||||||
|  | This article will focus on "safe" Rust only; `unsafe` mode allows you | ||||||
|  | to make use of platform-specific allocation API's (think the [libc] and [winapi] | ||||||
|  | implementations of [malloc]) that we'll ignore. We'll also assume a "debug" | ||||||
|  | build of libraries and applications (what you get with `cargo run` and `cargo test`) | ||||||
|  | and address (hehe) "release" mode at the end (`cargo run --release` and `cargo test --release`). | ||||||
|  |  | ||||||
|  | Finally, while the details are unlikely to change, the Rust docs | ||||||
| include a warning worth repeating here: | include a warning worth repeating here: | ||||||
|  |  | ||||||
| > Rust does not currently have a rigorously and formally defined memory model. | > 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) | > - the [Rust docs](https://doc.rust-lang.org/std/ptr/fn.read_volatile.html) | ||||||
|  |  | ||||||
| # Non-Heap Memory Types | # Stacking Up: Non-Heap Memory Types | ||||||
|  |  | ||||||
|  | Languages like Java and Python do an amazing job of simplifying the memory model | ||||||
|  | needed for programmers. You can essentially treat  | ||||||
|  |  | ||||||
|  | Most of the reason this post was written is because I  | ||||||
|  | Everyone's agreed that [compilers](https://www.youtube.com/watch?v=bSkpMdDe4g4) are | ||||||
|  | [smart](https://www.youtube.com/watch?v=nAbCKa0FzjQ), and Rust is no exception. | ||||||
|  |  | ||||||
|  |  | ||||||
| Example: Why doesn't `Vec::new()` go to the allocator? | Example: Why doesn't `Vec::new()` go to the allocator? | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user