I just picked up a 10-year old copy of O’Reilly’s Practical C, 3rd Edition from the library for some light reading. Mostly, I just wanted to see if I would learn anything (as a guage of my own C proficiency). I’m glad to announce that I learned almost nothing, until, that is, I read page 258, The Power of Powers of 2.
This page is in the section on optimization. Before I go further, I must say that I agree with the author, that when it comes to code optimization: don’t. With that aside, let’s proceed.
I have seen a lot of C arrays declared and allocated with a power-of-2 size (like 256):
int *values = (int*)malloc(256);
And I never really knew why coders used sizes of 256, instead of 200 or some other more “comfortable” number. I figured that it did something to make the code “better”, but I didn’t know exactly what. Today, I found the answer. Most C compilers will optimize this:
x = x * 8;
x = x < < 3;
The left shift operation requires fewer cycles than the multiply operation, so malloc() can get its job done faster when calculating how many bytes to allocate.
The fact is also true for accessing elements of multi-dimensional arrays. Take, for example, the following matrix:
When accesing an element in this matrix array, say element (12,39), the compiler has to do the following computations:
base_address + 12 * 256 * sizeof(int) + 39 * sizeof(int)
The 12 * 256 can be optimized to 12 << 8, making each array access a tiny bit faster. In code where this is happening a lot, it may even make a difference.
I guess this also explains why there is no 3-byte integer type, while there are 2-byte and 4-byte integers. And there will likely never be a 6-byte integer either.
Anyway, when it comes to optimization, there is so much voodoo and black magic in play that it’s really hard to know what provides the most bang for its buck. I might not even be right on this account either. Please correct me if you know better.