12

This is a very simple question:

Does 0-initializing global and static variables have any performance penalty (albeit very small) at runtime?

Dean
  • 6,610
  • 6
  • 40
  • 90
  • 1
    Normally the variables with static storage duration are put into the `.DATA` block of your executable, and it's zeroed at code generation time. So the answer is 'No' to the best of my knowledge. Actually, I think historically this is the reason why variables with static storage duration are zero-initialized - because it doesn't have any penalty. – Rostislav Oct 14 '15 at 13:35
  • @Rostislav Does it mean that the loader performs something like `memcpy(loading_address, address_of_data_section_with_zeroes, size_of_data_section)` ? – Dean Oct 14 '15 at 13:37
  • @Rostislav, generally speaking, you are incorrect, since you are missing a very important point - default-initialization of non-pods. – SergeyA Oct 14 '15 at 13:38
  • When your executable is loaded into memory, the variables with static storage duration are already there. No need for memsets. – Rostislav Oct 14 '15 at 13:38
  • @SergeyA Thus this is a comment - I know that I don't know enough on the subject. But I'm pretty sure it has some merit. – Rostislav Oct 14 '15 at 13:38
  • @SergeyA Also, the question is about zero-initialization :) – Rostislav Oct 14 '15 at 13:39
  • @Rostislav, however, the tag is C++ - so I believe we should not constrain ourself with just one example of default-initialization. – SergeyA Oct 14 '15 at 13:41
  • penalty compared to what? arent global and static variables always initialized? – 463035818_is_not_an_ai Oct 14 '15 at 13:42
  • On almost every system, there's a distiction between `.data` = non-zero initialized variables and `.bss` = zero-initialized variables. Typically these two segments are close buddies though, allocated next to each other and together forming the "local data" section of the RAM. – Lundin Oct 14 '15 at 13:51
  • Are you referring to the concept of `zero initialization` in the standard, or are you referring to initializing a value with the token `0`? – Yakk - Adam Nevraumont Oct 14 '15 at 14:10

2 Answers2

12

No, since the C++ (and C) standard says that all global/static variables that are not initialized explicitly by the programmer, must be initialized to zero. Such variables are placed in a special segment called .bss. They are initialized to zero before main() is called.

If you initialize your global/static explicitly, but to the value 0, the compiler is smart enough to realize this and still put it in the bss segment.


You can test this for yourself with an example like this:

#include <stdio.h>

static int uninit;
static int init_zero=0;
static int init_one=1;

int main (void)
{
  printf("%p\n", &uninit);
  printf("%p\n", &init_zero);
  printf("%p\n", &init_one);

  return 0;
}

In this example, the uninit and init_zero variables will end up at adjacent memory addresses (likely 4 bytes away from each other), since they are both in the .bss segment. But the init_one variable will end up somewhere else entirely, because it is allocated in the .data segment.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 2
    The standard says that they have to be zero-initialized, but the I doubt there's anything about `.bss` segment. So there _could_ be an architecture where zero-initialization is performed at run-time - is this correct? – Rostislav Oct 14 '15 at 13:42
  • @Rostislav Even though the standard doesn't mention it, `.bss` is traditionally the name of that segment on almost every platform out there, from 8 bit microcontrollers to 64 bit PC. In practice, pretty much every application does this in run time. Even on a RAM based system such as a PC, there's always various code executed before the program is started. On a ROM based system such as a microcontroller, the program has no other choice but to perform the so called "zero-out" in run time. – Lundin Oct 14 '15 at 13:45
  • [This answer](http://stackoverflow.com/questions/9535250/why-is-the-bss-segment-required/9535579#9535579) gives an example. – Lundin Oct 14 '15 at 13:46
  • 1
    As a side note, embedded systems typically have an option "minimal startup", which will remove the initialization of static storage variables entirely. This is non-standard and mainly used in C applications, for fastest possible startup. In C++, you have to execute the constructors of all static storage objects in addition to static initialization, so you really want all the start-up code to get chewed through before main() is called, or your program might go haywire. Actually a perfect example of when C is much faster than C++ :) – Lundin Oct 14 '15 at 13:56
  • Neither the common mechanism (.BSS) nor the fact that the initialization occurs before the start of main, tell you whether there is overhead to the zero initialization. In traditional C systems, part of the job of the C runtime library was to zero out .BSS (because that was memory allocated from the OS with random nonzero contents). For security reasons, modern OS's may not let you allocate pages that have not been pre-zeroed. A C run time library may be coded for such an OS and **might** avoid the overhead of zeroing .BSS (thus the relative overhead asked about in the original question). – JSF Oct 14 '15 at 13:57
  • @JSF I believe the OP is simply asking if there is a performance difference between `static int x;` and `static int x=0;`. – Lundin Oct 14 '15 at 14:00
  • @Rostislav There is some overhead at startup, but typically less than there would be if it had been part of the .data section. BSS takes up the same space but does not need to be loaded, where something in .data would have to be loaded too (and possibly cause the executable to be larger, causing it to take longer to load). – dascandy Oct 14 '15 at 14:01
  • @Lundin: "minimal startup" is really a sign of limitations in the compiler toolchain. Such a startup works when you explicitly initialize those variables yourself, in which case the optimizer could already remove zero-initialization regardless. – MSalters Oct 14 '15 at 14:06
  • I'm not sure how the "No" fits the rest of the question; just because it happens *before* `main` doesn't mean it isn't "run time"? – Yakk - Adam Nevraumont Oct 14 '15 at 14:11
  • @MSalters No, "minimal startup" it is a way to dodge the standard requirements for initialization. Typically "minimal startup" would break things like `static int x=1;`, x will never get initialized despite the code and you'll have to adapt the code accordingly. It is a bare metal embedded systems thing though, I doubtone will ever encounter it elsewhere. – Lundin Oct 14 '15 at 15:41
  • 1
    @Yakk "No" as in it will not save any time, because there is no way you can avoid the zero initialization anyhow. No matter how it is done by the compiler. – Lundin Oct 14 '15 at 15:42
  • Your choice of static, as opposed to automatic (ordinary declaration within a function) should be made for reasons a lot more important than whatever trivial overhead is involved in default initialization of static. But that doesn't mean you can't compare the choices on that basis and discover that an uninitialized stack variable is trivially more efficient **on some platforms** than a default initialized static or global. – JSF Oct 14 '15 at 22:16
-3

Extending the question from 0-initialization (which is just a subset of) to default initialization, we still can conclude that it usually has no measurable impact on application performance. However, it is easy to design a class which will do, for example, database lookup in it's constructor - thus leading for interesting effects noticeable during application startup.

SergeyA
  • 61,605
  • 5
  • 78
  • 137