2

At this moment of Jason Turner's 2016 CppCon talk "Practical Performance Practices", he mentions that full constexpr enabling of every data structure that can be (I'm guessing that means making every field and function constexpr that can be) can result in bigger code "because this causes more data structures to be compiled into your code so you have more data in the data segment than something that would be calculated at runtime" (this quote is kind of a combination of what he actually said at this time stamp and what he said at the end as an answer to a question about this topic).

I don't really understand what that means. Why would constexpr data structures compile to be bigger than non-constexpr data structures? Does anyone have an actual example that shows this?

1
  • 2
    As long as it's constexpr it's up to the compiler to decide whether to compute at compile time or run time. So if you optimize for size it should remain code. But if you optimize for speed then nothing beats having the data pre-computed. But see Davids answer for why it can increase the binary size (which can actually reduce the memory size). Commented May 15, 2022 at 22:13

1 Answer 1

3

When implementing a 7-bit cyclic redundancy check (CRC) algorithm on a microcontroller, I find it handy to build a 256-byte lookup table ahead of time, with some code like this:

uint8_t crc_table[256];
for (unsigned int i = 0; i < 256; i++)
{
  crc_table[i] = some_crc_function(i);
}

So if you turn crc_table into a constexpr thing that gets computed at compile time, your toolchain would have to store a 256-byte table in your executable, which takes up space. It would also be able to remove the code for generating the CRC table, but if the machine instructions for that code take less than 256 bytes, then I'd expect the executable to get bigger.

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

6 Comments

Thanks for the example, I think I get it now. Whether crc_table is constexpr, it still needs to exist somewhere in memory when the program executes. If it is local to a function, it would just be on the stack and not in the executable itself but if it is global/static then it is in the executable, whether or not it is constexpr (so there is no space savings in the global/static case)?
@bun9 A global array that's initially all zeroes an initialised by calculation requires no storage in the executable (except for the instructions which doesn't scale by the size of the array). If the content is calculated at compile time, then the result of the calculation has to be stored in the executable.
@bun9 In the case it's initialised dynamically, it would be in the BSS segment.
Note that this increases the size of the binary but not the memory requirements of the program. For constexpr the array also lands in the rodata section of the binary, which is mapped into memory (at least on Unix systems), will only be read when used and can be swapped out simply by forgetting it. So this actually reduces the memory pressure.
Answering bun9's earlier questions, a global variable declared with simple code like uint8_t crc_table[256]; gets initialized to 0, so its contents do not need to be stored in the excutable. There will be some metadata about it, but there is no point for the executable to hold 256 zeroes just to represent that variable. That would be a bad OS design.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.