@Joe232 I would say that maybe the concepts that you mention wanting to understand more about, the stack and heap at least, are actually somewhat unnecessary to have a very competent understanding of Rust and the ability to put it to effective use.
More important are the basic concepts of borrowing and a thorough understanding of things like
Results, and Iterators and how to use control flow mechanisms such as loops, if statements and
match statements and how you can use the strengths of
Results to idiomatically solve common programming patterns.
On top of those I would start to understand generics and traits a bit more, maybe. Then probably lifetimes.
async is also really good to understand, but it depends on what you are working on whether or not you need it and how soon you should learn it.
Also important in a different way is getting a knowledge of the ecosystem and what crates are out there for accomplishing certain tasks. For instance, I spent a while early on really confused at how to accomplish certain things because I didn't know about the
lazy_static crate ( don't worry about looking it up yet ).
These things will mix a bit and you will have to be exposed to certain portions of the more advanced components early on without understanding exactly why things are a certain way, but that is that nature of learning. You will build on the foundational pieces bit by bit and eventually you will learn things that make the things you learned earlier on make a lot more sense.
But you don't need to really dig into a lot of these topics way too much to write effective Rust. I actually don't have a full understanding of the stack or the heap, but I do have a great grasp on Rust. If you're still curious as to my picture of the stack and the heap ( it may not be 100% accurate, but it is good enough to understand Rust ):
The stack: is a place in memory where you can store things that you know the exact size of at compile time. There is a limit to the size of the stack but it is also very fast to access and modify. In general local variables for types such as numbers, arrays, and anything that doesn't have a dynamic size such as
Vec are automatically stored on the stack.
The heap: is like a big pool of memory that you can request chunks of from the operating system ( or allocator, actually, I think ) to store your stuff in. For example, you program can just go and ask the allocator for a spot somewhere on the heap that is 56 bytes long, and the allocator will go search its memory for a spot that can fit 56 bytes and it will give your program access to that memory so you can stick whatever you want in it.
The heap is where things like strings that aren't string literals go. Your program can't know at compile time what the length of a string is going to be before it exists, so instead of storing it on the stack, when running something like
String::from("hello world"), rust will go find enough space in memory to store
"hello world" and then the
String object will point to that place in memory.
An important characteristic of the heap is that finding spots for stuff is slow ( relatively anyway ). This is referred to as "allocating". When you create a Vector like this,
vec![1, 2, 3], the
Vec will allocate enough memory to store 3
i32s ( the default integer type ). You program will have to wait for the allocator to find a spot in memory to put your
i32s. This can happen as far as humans can tell, unless you have to do many, many allocations very quick.
When tuning for performance one key is to be conscious about making as few allocations as you can in the areas of your program that get executed very often or in loops.