# Variable size and CPU performance

When you learn programming they tell you choose data types that suffice for the concepts you're expressing, i.e. not too small because then your data won't fit and not too big because you don't want nonsensical values stored.

Table of unsigned integers

• 8-bit: 0 to 255
• 16-bit: 0 to 65,535
• 32-bit: 0 to 4,294,967,295
• 64-bit: 0 to 18,446,744,073,709,551,615

According to the table above, an 8-bit unsigned integers can store e.g. the number of weeks in a year (approximately 52) and a 64-bit unsigned integer can store e.g. astronomical values.

To get to the point of my question; how do the different variable sizes affect the performance of a program? I imagine that a 64-bit CPU internally handles all variables as 64-bit and simply ignores the highest bits, so an 8-bit variable, travelling across the system, would be handled as:

xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx yyyyyyyy


Where y is either 0/1 and x is ignored.

Would it make any difference performance-wise to only use the largest variable size on the platform and use business logic to enforce reasonableness in the values being processed and stored? Is there a performance hit when using variable sizes lower than the native variable size of the architecture?

• No, not all variables are handled as 64-bit, they are handled using precisely the number of bits as their name suggests, e.g. uint8_t uses 8 bits. That's why when you add 2 to an uint8_t variable with 255 as its value, you get 1 (i.e., the overflow is truncated). – xtt Sep 28 '17 at 5:22
• And what about performance of different sizes? – user8056359 Sep 28 '17 at 9:54
• that will depend on many aspects. For example, different instruction sets have different ways of manipulating data. For modern cpus, handling data with standard sizes (8, 16, 32, 64 bits) most likely has optimized routines, so I guess besides memory consumption (which will affect performance during read and write), the total number of cycles won't differ that much. Besides, different compilers will have different optimizations, which will also affect performance. – xtt Sep 28 '17 at 10:06
• x86 Intel 64-bit CPUs have 8-bit, 16-bit, 32-bit and 64-bit registers, they also have commands for reading 32-bits or 64-bits etc, they don't work exclusively with 64-bit operations. Others have explained this well, just adding a related interesting read: stackoverflow.com/questions/25078285/… – jwbensley Oct 17 '17 at 18:31

Would it make any difference performance-wise to only use the largest variable size on the platform and use business logic to enforce reasonableness in the values being processed and stored?

Yes, it could make your performance worse.

Memory, memory bandwidth, cache density are primary concerns. Larger data size can:

• result in increased cache and translation lookaside buffer (TLB) misses;
• require more RAM to avoid paging.

E.g. x86 CPUs always load (if not already in cache) a whole cache line from memory.

So, assuming a cache line of 64 bytes, there are 64 8-bit-integers per cache line, yet only eight 64-bit-integers. Thus resulting in eight times as many memory transfers for processing a large array.

Also consider that many compiler are smart enough to figure out how to perform automatic vectorization1.

Taking advantage of the processor's SIMD capabilities you can pack eight 16-bit integers into the same space as two 64-bit integers and do four times as many operations at once.

Is there a performance hit when using variable sizes lower than the native variable size of the architecture?

There isn't a general rule.

x86 CPUs can operate on fractions of a register and there will be no slow down at all2.

Other CPUs (e.g. PowerPC) cannot process a fraction of a register. So performing multiple operations on small integers may require masking / cutting back partial results. Anyway it's just a simple AND operation and often the compiler can find a way to avoid it entirely.

As a corner case some instructions can be slower when performed with the CPU's "native size" (e.g. multiplication / division of 64-bit quantities vs 32-bit quantities on Intel Pentium IV).

1) automatic vectorization is a major research topic in computer science

2) x86 processors can suffer a partial register stall if you, say, write to BX and then try to read from EBX (something to consider mixing integer of different sizes).

I would say it depends on the application and target architecture.

Usually the x86 is the main target, but practices used there might not transfer well into a embedded domain.

Other architectures (usually RISC) have large amount of registers, AVR has 32 registers 8-bits each and it's possible use finer granularity as some instructions have bit wise manipulation.

For example RISC-V has 32 register 32-bit each (or 64-bit or 128-bit depending on the implementation), there the registers are dedicated to pushing arguments between functions without using stack/memory and using a lot of variables might end up being allocated to registers anyway, forcing it to non-native (smaller) size can cause unecesary modulus and other operation to mimic features which now are not given for free by hardware (as there might not be dedicated instruction using smaller type) because the code insists using using smaller type and expects behavior of a smaller type and can't use the native type. So in some cases you will not save on memory size, nor on memory accesses, you will just force CPU to do awkward things because you think it will make it run faster.

When RISC-V has floating point unit implemented then it gets yet another set of registers to work with, so for example rv32-imaf will have 64 registers. So it can really do a lot without touching a stack/memory.

• Welcome to COMPUTERSCIENCE @SE. Using Other architectures, what/which are you referring to as non-other? – greybeard Sep 9 '20 at 6:16
• x86 looked to me as the main one here in this thread, but in essence probably the CISC architectures will have less registers and using more memory and depend more on stacks (for local variables, function arguments, return values) where having smaller types could be beneficial (as CISC might have dedicated instruction to deal with a non native types as well). While RISC often has a lot of registers and no dedicated instructions to deal with non-native types, which means that it will not get memory benefit from using a smaller type, but it can get instruction penalty using non-native type. – Anton Krug Sep 9 '20 at 14:19