4

This may sound like a question with an obvious answer, but please bear with me.

Why is it useful that the Rust compiler knows the size in memory a type takes at compile time?

Is this used for some optimization? if so what kinds?

Can one infer the size of the binary produced from the size of the types? That is, will a program using the i128 type produce a bigger binary compared to a program that uses u32? Or this "knowing of types" only affects the size of the memory the program will use at runtime?

2
  • 1
    It reflects the range of values that can be stored in the variable. Which enables range checking. And controls overflow or panic when the value exceeds the range. For example, what is -1? Also, it can enable to address hardware (in some circumstances). Commented Oct 15, 2022 at 0:13
  • a program that uses i128 will produce a bigger binary than i32 not because of the extra size of the numbers but because computers only have hardware that deals with 64 bits, so it must generate a lot more code for operations to manually handle the extra 64 bits without hardware support. Commented Oct 15, 2022 at 0:13

1 Answer 1

4

Knowing the size of the types in your program lets the compiler do a bunch of things:

  • Allocate the correct amount of memory for stack frames (since all your local variables are on the stack).
  • Allocate the correct amount of memory when heap-allocating a value.
  • Reason about things in the type system regarding sized-ness.

Additionally, this is beside any optimizations that the compiler can do, for example: size_of::<Option<Box<usize>>>() == size_of::<Box<usize>>(), since a null pointer is an invalid bit pattern for Box and can therefore be used to represent None.

This doesn't really affect the size of your binary in any meaningful way. Chances are that the biggest thing which affects that is actual code rather than data. Technically, different types often have different instructions, so yes, different types could result in differently sized binaries, however any difference because of that is probably overshadowed by other things (such as generic monomorphization of functions).

At runtime, the size of your data does matter however. For example, 4 million u8s have the size of 4mb, however 4 million u128s have the size of 64mb.

However, knowing the size of the types in your program is simply part of compilation -- it's not something that can be turned off and is something that the compiler could not function without knowing.

Sign up to request clarification or add additional context in comments.

4 Comments

Coming back to his answer and I have questions. You mentioned that "Allocate the correct amount of memory for stack frames (since all your local variables are on the stack)" but allocating memory for stack frames is done at Runtime not compile time. Is it that during compilation, this information is needed to be embedded in the binary so it is available at runtime?
I mean, dynamic languages don't have the luxury of a compile time to know the types and yet, they work....so what is the difference?
@FinlayWeber You are indeed correct that stack frame allocation is done at runtime (and languages like C let you allocate more of your stack with alloca), however Rust doesn't let you do this. I'm not 100% sure why, however I wouldn't be surprised if it happened to have something to do with drop flags.
@FinlayWeber Dynamically typed languages indeed don't have the luxury of a compiletime to know types. But they also work wildly differently to statically typed languages. Namely, in dynamically typed languages, most "complex objects" are actually heap-allocated (the meaning of this may differ, for example GC languages have their own special heap they manage themselves). Doing this reduces the size of everything on the stack to something manageable (integers, floats, etc., and pointers to objects).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.