Home > database >  Optimize memory by variable arrangement
Optimize memory by variable arrangement

Time:04-03

I have just been taught a new knowledge about how to optimize memory .
Concept says: Variable will always be stored in an area of ​​8 bytes, if not 8 bytes it will be filled with padding.
You can see the illustration with the photo.

Memory Alignment

I tried to test it with the sizeof() command, ironically it didn't work as expected. Is that correct? How do I prove it with code?

CodePudding user response:

I think you have misunderstood or misstated what you have been taught. The statement:

Variable will always be stored in an area of ​​8 bytes,

is not supported (in fact explicitly contradicted) by your diagram, and if that were true, no amount of "variable arrangement" would have any impact on memory usage because all members would occupy the same space with padding. That is not what the diagram illustrates at all, and I suspect not what you were actually taught.

It is in any event implementation defined, and 8, 16, 32 and 64 bit platforms for example may have differing optimal alignment and a compiler may or may not generate optimal performance alignment if the optimisation goal is minimal space, or compiler directives or options are applied to force different alignment.

For example; what your diagram suggests is that if the bool and the double were swapped, the structure size could be 16 rather than 24 bytes long.

Regarding:

How do I prove it with code?

well since it is implementation defined, you could equally disprove it on some platforms/compiler implementations. However to test the hypothesis, and to investigate any specific implementation, consider:

#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>

int main()
{
    struct 
    { 
         bool a ; 
         double b ;  
         uint16_t c ; 
         uint32_t d ; 
    } foo ; 
     
    struct 
    { 
         double b ;  
         bool a ; 
         uint16_t c ; 
         uint32_t d ; 
    } bar ; 
     
    printf("foo: %lu\n", sizeof(foo) ) ;
    printf("bar: %lu\n", sizeof(bar) ) ;

    return 0;
}

At https://onlinegdb.com/jknxFt0Sx at least, it outputs:

foo: 24
bar: 16

Which demonstrates the behaviour suggested in your diagram, but clearly disproves "Variable will always be stored in an area of ​​8 bytes,...".

More importantly the take home here is that generally the ordering of members dependent on their respective sizes can affect the overall size of the structure after implementation defined alignment and padding have been applied.

What the diagram actually illustrates is that members are aligned depending on their size. So single bytes can have any address, 16 bit types have even addresses, 32 bit types have addresses divisible by 4, and 64 bit types by 8. Now that may or may not be true in any particular implementation, but the way to minimise the size of a structure where that is true, is to group members such that they are packed with no padding while maintaining required alignment.

Generally the default alignment can be manipulated (by compiler defined mechanisms). For example in gcc:

    struct 
    { 
         bool a ; 
         double b ;  
         uint16_t c ; 
         uint32_t d ; 
    } __attribute__((packed)) foo ; 
     
    struct 
    { 
         double b ;  
         bool a ; 
         uint16_t c ; 
         uint32_t d ; 
    } __attribute__((packed)) bar ; 

Results in both structures having a size of 15 regardless of the platform's preferred or required alignment. On platforms where unaligned access is not supported, such structures generate additional code to access unaligned members, and may in some (mis)uses cause an exception.

CodePudding user response:

You confuse size with alignment

A char is always size 1, its defined by the c standard.

Alignment means, is the address of that variable a multiple of some particular value (usually 2, 4, 8 or 16).

Why are variables aligned? On some CPUs various type of data must begin on an even boundaries or even multiples of 4. Other CPU types perform much better with data that is well aligned. Compilers know this and so they will layout things in memory to be correctly and / or optimally aligned.

See

Why is integer assignment on a naturally aligned variable atomic on x86?

INTEL X86,why do align access and non-align access have same performance?

Alignment results in unused memory between variables.

THe sizeof operator tells you the size of the variable regardless of how its aligned. It does not take alignment into account.

  • Related