What are the pros and cons of using bit field for boolean etc?

I was looking through Shooter Game code, and I spotted usage of bit field for stuff like booleans etc. I come from Unity environment so I’m not used to them. However I love optimization so I will stick to them.

But what pros and cons we get from using it? How much it actually helps with RAM usage when more and more people have 8GB RAM. Dose it help with CPU cache?

I’d also like to know this. My suspicions are that defining a bool as “int32 bFoo:1;” reduces bandwidth overhead for network replication, since it only needs to pack 1 bit instead of 8/16/32 bits (whatever the default size of a bool is on the platform). But this is just a guess based on past C++ projects.

I’m not sure this is correct, as it really depends on the compiler and architecture. There is a performance overhead packing/unpacking bits, and many CPUs have instruction sets that are optimised for byte/word-aligned data structures. It definitely reduces memory overhead, though on modern platforms that’s negligible. I feel like there’s another reason at play.

It is quicker in certain cases. Eg. if you use a regular bool (1 byte), and you need to set 8 bools to various values, you have to write 8 bytes. With 8 bits, you only need to write 1 byte.

Basically, you can compress many more into a single byte when using bit fields.

8 bytes as bools: 8 boolean values

8 bytes as bits: 64 boolean values

(Granted that they’re not separated)

I was referring specifically to setting all the values at once.

If you write 64 values as bool, the CPU has to write 64 bytes, while using bits only needs to write 8 bytes.

Or with 8 values, 8 bytes with bools, 1 byte with bits:


As bools:

C++:

bool a; //true

bool b; //true

bool c; //false

bool d; //true

bool e; //false

bool f; //false

bool g; //true

bool h; //true

ASM:

//eax = address of a.

mov dword ptr ds:[eax], 0x01000101

mov dword ptr ds:[eax+4], 0x01010000


As bit field:

C++:

bool a : 1; //true

bool b : 1; //true

bool c : 1; //false

bool d : 1; //true

bool e : 1; //false

bool f : 1; //false

bool g : 1; //true

bool h : 1; //true

ASM:

//eax = address of a.

mov byte ptr ds:[eax], 0xCB

Thanks for the clarification - makes sense.

There’s also considerations to make when thinking about the cache/instruction pipeline. Specifically the “cache line”. One should test if optimizations matter. I like having large counts of game objects in my worlds though and that generally means being very careful with memory not just for bandwidth but for the cache line’s sake. I guess it’s somewhat less important for polymorphic code that uses a ton of pointer logic. But it should still matter somewhat regardless at least in some areas. If your reading lots of data per frame there’s things that one can do to help, read contiguous, read less, avoid indirection as much as reasonably possible.