How to tell compile time vs run time code?

Not necessarily in one specific scenerio, but in general, how can you determine when code will be evaluated at compile time?

I found the following link, and feel like the answer might be right in front of me, but I don't quite understand the text. Maybe I just need examples..
https://doc.rust-lang.org/reference/const_eval.html

So far, I know that

  • const variables will be evaluated at compile time
  • Code that's not called will not be in the binary

But I'm not sure about other scenerios. Technically I should learn Assembly... but that seems daunting at this time and I wonder if some more experienced Rust folks have found any hard and fast rules for different kinds of scenerios.

Here's an example

fn main() {
  // The builder uses types behind the scenes
  // that won't be used anywhere else, they're
  // "temporary"
  let mut tmp_robot = Builder::new()
                        .add_arm()
                        .add_wheels();

  init(tmp_robot);
}

fn init(tmp: TmpBot) {
  // Build the more efficient runtime
  // representation of robot
  let bot = Bot::new(tmp);
  // This is basically the real start
  // of the program and could have
  // user inputs and things
  simulate(&bot);
}

My assumption with the above example is that everything before let bot = Bot::new(tmp); will be evaluated at compile time since the program no longer uses anything from before and there was no blocking code yet, like asking for user input or something.

I tried using const fn but wasn't able to because I use loops and Vecs, and probably some other things. None of it sticks around during the program, but if it ends up in the binary.. That's the question.

You mention Vecs, which use allocation. Allocation is very rarely optimized out at compile time, so it's unlikely things like that will be completely removed.

That being said, are you concerned about the performance if it does not get optimized away? Have you benchmarked the result to see if it will really cause you problems?

It changes with every compiler version. There is no guarantee of consistent assembly code, only that it works. (Multiple ways the source can be represented with machine instructions.)

1 Like

Performance, yes, but also memory.

It's mainly the fact that I know how the end result should be structured, but since I'm trying to provide a nice API for generating that structure, I can't start out with that structure.

So, I'm using "temporary types" for the Builder.

e.g.
TmpBot and Bot have a parts field. TmpBot.parts has type Vec<TmpBot> where Bot.parts has type BTreeMap<String, usize>.

TmpBot might nest other TmpBots and so on. However, at runtime I just store an index to a flat, fixed array.

Before the program is supposed to run, the contents of the final array will be known (because they're collected during init()) and will never change during runtime.

I haven't measured the performance yet. It just feels like leaving the light on when leaving a room..

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.