What are some good guidelines for sizing integer types?

I searched a bit, and in fact I really have no answer.

When I program on embedded devices with limited memory, I'm usually used to using the smallest type of integral / floating point that will do the job, for example, if I know that the counter will always be between zero and 255, I will declare it as uint8_t .

However, in less restricted environments, I use only int for everything that matches Google C ++ Styleguide . When I look at existing code, this is often done like this.

To be clear, I get a rationale for this, (Google explains it very well), but I do not quite clearly explain why I am doing something in the first place.

It seems to me that reducing the memory size of your program, even on a system in which you do not care about memory usage, would be good for overall speed, since logically less general data could mean that it fits more into the processor cache.

However, it is complicating that the compilers will automatically place the data and align it to the borders so that it can be loaded in one bus cycle. I believe that it comes down to whether the compilers are smart enough to take, say, two 32-bit integers and combine them into one 64-bit block, and individually defer each of them to 64 bits.

I suppose whether the processor itself can use this also depends on its exact internal components, but the idea that optimizing memory size improves performance, especially on new processors, is confirmed by the fact that the Linux kernel has been running for some time for the option gcc -0s for better performance.

So, I think my question is why the Google method seems to be much more common in real code. Is there any hidden cost here that I am missing?

+6
source share
4 answers

The usual reasons why the google method is usually used, because int often good enough, and this is usually the first option taught in the beginner's material. It also takes more effort (man-hours, etc.) to optimize non-trivial code for "limited memory" - efforts that are pointless if not needed.

If "actual code" is written for portability, then int is a good default choice.

Whether written for portability or not, many programs run only on hosts with sufficient memory resources and with an int type that can represent the required range of values. This means that there is no need to worry about memory usage (for example, optimizing the size of variables based on a certain range of values ​​that they should support), and the program just works.

Programming for "limited memory" is certainly common, but it is not typical why most of the code is written. Quite a lot of modern embedded systems have more than enough memory and other resources, so methods are not always needed for them.

A lot of code written for what you call "limited memory" is also not really necessary. There is a certain point when programmers learn more that a significant number begin to indulge in premature optimization - to worry about performance or memory usage, even if there is no need for them. Despite the fact that due to the true need, of course, there is a significant part of the code written for "limited memory", much more of this code is written due to premature optimization.

+2
source

"embedded devices ... counter from zero to 255, I will declare it as uint8_t"

This can be counterproductive. In particular, on embedded systems, 8-bit samples may be slower. In addition, the counter is probably in the register, and there is no use in using half the register.

The main reason for using uint8_t is when you have an adjacent set of them. May be an array, but also adjacent elements in the class .

As comments have already been noted, -Os is irrelevant - the advantage is that with a smaller code, the memory bus has more bandwidth for the data.

+2
source

In my experience, 90% of all code in a larger project does not need specific optimization, since 95% of all memory consumption and total execution time is spent less than 10% of the code you write. For the rest of the code, try to emphasize simplicity and ease of maintenance. This basically means using ints or size_t as integer types. As a rule, there is no need to optimize the size of local variables, but this may make sense if you have many instances of the type in a large array. Point 6 in the excellent C ++ book. Coding Standards: 101 Rules, Recommendations, and Best Practices (C ++ In-Depth) by Herb Sutter and Andrei Alexandrescu states:

"First correctness, simplicity and clarity."

The most important thing is to understand where these less than 10% of the code that really need optimization. Otherwise, simplify and simplify the interfaces.

0
source

Good discussion! But I wonder why no one talks about processor register size, memory bus architecture, processor architecture, etc. The statement "int is best" is not general at all. If you have small embedded systems like 8 bits avr, int is a very bad choice for a counter starting at 0 .. 255.

And using int on ARM, where you can have a 16-bit bus interface, can also be a very bad idea if you really only need 16 bits or less.

As with all optimizations: look at the code that the compiler produces, measure how long the actions take, and look at the memory consumption on the heap / stack, if necessary. It does not make sense to distribute an unbearable code to save 8 bits somewhere if your equipment still has MBytes.

Using tools like valgrind and profiling supported by the target / compiler gives a lot more ideas than any theoretical discussion here.

There is no general "best integer type"! It always depends on the processor architecture, memory bus, caches and some others.

0
source

All Articles