Browse DevX
Sign up for e-mail newsletters from DevX


Optimize Your Member Layout-3 : Page 3




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Member Reordering
When a data structure contains members whose total size is odd, it's best to let the compiler round the size up. In the case of Broadcast, letting the compiler round its size from 7 to 8 bytes is acceptable. However, because of the random order in which data members are declared, the size of Broadcast is further augmented to 12. This isn't acceptable. It's this leap from 8 to 12 bytes that you wish to avert. To help the compiler out, ensure that members whose size is smaller than the default alignment unit (4 bytes in this example, or sizeof(int) in general) are adjacent. This is like laying out Lego bricks: instead of using one large brick, place two small bricks together. Let's look at the current inefficient memory layout of Broadcast's members:
  • timezone: occupies one byte for itself and three additional padding bytes
  • frequency: occupies four bytes for itself
  • timeofday: occupies two bytes for itself, two for padding
The three padding bytes inserted after timezone are large enough to accommodate timeofday. Reorganizing Broadcast like this:

struct Broadcast { char timezone; //hasn't moved short timeofday; //originally was #3 int frequency; //originally was # 2 };

reduces its size to 8 bytes! The members are now aligned as follows:
  • timezone: occupies one byte for itself and one padding byte
  • timeofday: occupies two bytes for itself
  • frequency: occupies four bytes for itself
In terms of alignment, the compiler treats timezone and timeofday as a single member that occupies four bytes (including one padding byte). Notice that this size reduction is achieved without compromising design or tampering with the compiler's setting. Of course, this technique is applicable to all data structures, including classes and unions. The more data members a data structure has, the more space you can save by reordering them. Consider the following class:

class Page { private: bool swappable; //1 byte + 3 for padding void * address; //4 bytes short page_size; //2 bytes + 2 for padding int bytesused; //4 bytes bool readonly; //1 byte + 3for padding //..member functions };

The result of summing each member's size is 12 bytes. However, sizeof(Page) is actually 20, which means that 8 bytes, or almost half of this class's size, are wasted as padding bytes. Now, try to group members that occupy less than 4 bytes together:

class OptimizedPage { private: //the following 3 members make exactly one alignment unit bool swappable; //1 byte bool readonly; //1 byte short page_size; //2 bytes //each of the following 2 fits into one alignment unit void * address; //4 bytes int bytesused; //4 bytes };

This way, no padding bytes are required because the first three members fit exactly into an alignment unit. As a result, sizeof(OptimizedPage) is now reduced to 12.

Sizing Up
Code optimization usually boils down to rewriting heavily-used functions and poking into the generated assembly code. However, the member reordering technique shown here is one of the few optimizations that are simple and hassle-free. In memory-challenged systems, it should become a natural programming habit that will pay off very quickly. Even in desktop applications and server processes, it can be useful.

Danny Kalev is a certified system analyst and software engineer specializing in C++. He was a member of the C++ standards committee between 1997 and 2000 and has since been involved informally in the C++0x standardization process. He is the author of "The ANSI/ISO Professional C++ Programmer's Handbook" and "The Informit C++ Reference Guide: Techniques, Insight, and Practical Advice on C++."
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date