diff --git a/_drafts/a-heaping-helping.md b/_drafts/a-heaping-helping.md index 3ed807c..408a3ba 100644 --- a/_drafts/a-heaping-helping.md +++ b/_drafts/a-heaping-helping.md @@ -72,7 +72,7 @@ we'll follow this guide: - Smart pointers hold their contents in the heap - Collections are smart pointers for many objects at a time, and reallocate when they need to grow -- `lazy_static!` and `thread_local!` force heap allocation +- `lazy_static!` and `thread_local!` force heap allocation for everything. - Stack-based alternatives to standard library types should be preferred (spin, parking_lot) # Smart pointers @@ -166,7 +166,15 @@ will ever be dispatched. A couple of places to look at for confirming this behav [`HashMap::new()`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.new), and [`String::new()`](https://doc.rust-lang.org/std/string/struct.String.html#method.new). -# **thread_local!** and **lazy_static!** +# **lazy_static!** and **thread_local!** + +There are two macros worth addressing in a conversation about heap memory. The first isn't part +of the standard library, but it's the [5th most downloaded crate](https://crates.io/crates/lazy_static) +in Rust. The second + +TODO: Not so sure about lazy_static anymore. Is thread_local possibly heap-allocated too? +- Think it may actually be that lazy_static has a no_std mode that uses `spin`, std-mode uses std::Once. +- Reasonably confident thread_local always allocates # Heap Alternatives @@ -178,8 +186,8 @@ to know that alternatives exist if you need them. When it comes to some of the standard library smart pointers ([`RwLock`](https://doc.rust-lang.org/std/sync/struct.RwLock.html) and [`Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html)), stack-based alternatives -are provided in crates like [spin](https://crates.io/crates/spin) and -[parking_lot](https://crates.io/crates/parking_lot). You can check out +are provided in crates like [parking_lot](https://crates.io/crates/parking_lot) and +[spin](https://crates.io/crates/spin). You can check out [`lock_api::RwLock`](https://docs.rs/lock_api/0.1.5/lock_api/struct.RwLock.html), [`lock_api::Mutex`](https://docs.rs/lock_api/0.1.5/lock_api/struct.Mutex.html), and [`spin::Once`](https://mvdnes.github.io/rust-docs/spin-rs/spin/struct.Once.html) diff --git a/_drafts/stacking-up.md b/_drafts/stacking-up.md index 519ee55..c5492e8 100644 --- a/_drafts/stacking-up.md +++ b/_drafts/stacking-up.md @@ -100,6 +100,10 @@ With all that in mind, let's talk about situations in which we're guaranteed to - Generics will use stack allocation, even with dynamic dispatch. - [`Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html) types are guaranteed to be stack-allocated, and copying them will be done in stack memory. +- [`Iterator`s](https://doc.rust-lang.org/std/iter/trait.Iterator.html) in the standard library + are stack-allocated. No worrying about some + ["managed languages"](https://www.youtube.com/watch?v=bSkpMdDe4g4&feature=youtu.be&t=357) + creating garbage. # Structs @@ -451,12 +455,12 @@ used for objects that aren't heap allocated, but it technically can be done. # Copy types -Understanding move semantics and copy semantics in Rust is hard. The Rust docs +Understanding move semantics and copy semantics in Rust is weird at first. The Rust docs [go into detail](https://doc.rust-lang.org/stable/core/marker/trait.Copy.html) far better than can be addressed here, so I'll leave them to do the job. -Their guideline is reasonable though: +Even from a memory perspective though, their guideline is reasonable: [if your type can implemement `Copy`, it should](https://doc.rust-lang.org/stable/core/marker/trait.Copy.html#when-should-my-type-be-copy). -While there are potential speed tradeoffs to benchmark when discussing `Copy` +While there are potential speed tradeoffs to *benchmark* when discussing `Copy` (move semantics for stack objects vs. copying stack pointers vs. copying stack `struct`s), *it's impossible for `Copy` to introduce a heap allocation*. @@ -471,4 +475,19 @@ Thus, assignments involving heap types are always move semantics, and new heap allocations won't occur without explicit calls to [`clone()`](https://doc.rust-lang.org/std/clone/trait.Clone.html#tymethod.clone). -TODO: Some examples. Maybe just need to show compiler errors? +```rust +#[derive(Clone)] +struct Cloneable { + x: Box +} + +// error[E0204]: the trait `Copy` may not be implemented for this type +#[derive(Copy, Clone)] +struct NotCopyable { + x: Box +} +``` +-- [Compiler Explorer](https://godbolt.org/z/VToRuK) + +# Iterators +