5

Question: Is there an automatic way to do structure packing?

Background:

Structure packing is very useful to reduce the memory cost of certain fundamental data. Basically it is the trick to achieve minimum memory cost by reordering the data inside. My question is that is there an auto way to do that? For example, I have a struct Foo here.(suppose 32bit)

struct Foo {     
  char flag;
  char* p;
  short number;
};

After a auto check(either it is a script or not, native or not), I should get a memory-optimization version of Foo, which is:

struct Foo {
  char* p;
  short number;  
  char flag;     
};

This is just a toy example. Consider more difficult situations below, it would be quite a work for manual reordering.

  1. struct has dependent struct:

    struct Foo {
      char* p;
      short number;
      MoreFoo more_foo // How to deal with this?
      char flag;     
    };
    
  2. struct is in legacy code and you are not familiar with codebase.

  3. you want the code to be cross-platform. Sadly enough, this trick is compiler-dependent.

I am not considering using "packed" attribute since it will lead to some performance issue.

Can __attribute__((packed)) affect the performance of a program?

Community
  • 1
  • 1
qqibrow
  • 2,942
  • 1
  • 24
  • 40
  • 5
    This "trick" is dangerous in C++ wrt `struct`. The order of the parameters is important if the struct has a constructor that relies on the order of the members. – PaulMcKenzie Jan 12 '15 at 19:29
  • 1
    possible duplicate of [Why doesn't GCC optimize structs?](http://stackoverflow.com/questions/118068/why-doesnt-gcc-optimize-structs) – buydadip Jan 12 '15 at 19:33
  • 1
    see also...http://stackoverflow.com/questions/9486364/why-cant-c-compilers-rearrange-struct-members-to-eliminate-alignment-padding – buydadip Jan 12 '15 at 19:34
  • 3
    I don't know of any tool that would do that automatically, and you should note that reordering members is a binary incompatible change and will need to rebuild the world (well, the subpart that uses your type). There are tools like `pahole` (linux) that will not reorder but give you the information that you need to do this right, including where you have holes (padding) and where the different cache lines align (so that you can move hot members to the beginning of the object) – David Rodríguez - dribeas Jan 12 '15 at 21:02

2 Answers2

3

In C++03 you can give the compiler permission to reorder members by placing every one inside a separate access section, e.g.:

struct Foo
{
public:
  char* p;
public:
  short number;
public:
  MoreFoo more_foo;
public:
  char flag;     
};

Whether a particular compiler uses this additional flexibility or not I do not know.

This doesn't change the declaration order, it simply unlinks memory order from declaration order, so PaulMcKenzie's concern about initialization order does not apply. (And I think he overstated the concern; it is very rare for member initializers to refer to other subobjects in the first place)

The way this works is because it causes the following rule, from 9.2) to no longer have effect:

Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).

Also, it's questionable whether this still works in C++11, since the wording changed from "without an intervening access-specifier" to "with the same access control":

Nonstatic data members of a (non-union) class with the same access control (Clause 11) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified (Clause 11). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1).

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • While this is good to know, is there any compiler that actually rearranges members? I recall hearing that none took advantage of this. – Mooing Duck Jan 12 '15 at 20:09
  • @MooingDuck: Already said "I do not know". But I can guess that if any did, that would have been a big deal when the change in wording was proposed, so probably not. – Ben Voigt Jan 12 '15 at 20:09
  • It would probably have to be fully described in your C++ ABI in practice, since serious compiler writers want to avoid binary incompatibility. Most of the time. – Steve Jessop Jan 12 '15 at 20:48
  • @SteveJessop: Compatibility across different tools / tool versions / build options requires standard-layout classes. – Ben Voigt Jan 12 '15 at 20:52
  • @BenVoigt: are you asserting "there does not exist a C++ ABI that specifies layout for anything other than standard-layout classes?". Or are you merely asserting "the C++ standard doesn't require ABIs to do that"? – Steve Jessop Jan 12 '15 at 21:00
  • @SteveJessop: Asserting the latter as a matter of fact (the Standard describes layout as unspecified, not implementation specified), and also a matter of good coding style (when you want your binary interface to be specified/predictable/stable, do it via standard-layout) – Ben Voigt Jan 12 '15 at 22:06
  • http://stackoverflow.com/questions/15763091/do-these-members-have-unspecified-ordering – T.C. Jan 13 '15 at 00:14
2

In C programming, automatic optimization of a struct is not possible because this would go against the very way it was designed. C allows low-level access to the hardware, in fact, it is only a step higher from assembly language. It is designed to create dependent code that controls hardware.

Given this, unfortunately, you can only re-order a struct manually. You would probably need to find the size of all the struct's attributes, as so:

printf ("Size of char is %d\n", sizeof (char));
printf ("Size of char* is %d\n", sizeof (char*));
printf ("Size of short is %d\n", sizeof (short));
printf ("Size of MoreFoo is %d\n", sizeof (MoreFoo more_foo));

And then order the struct based on these values.

buydadip
  • 8,890
  • 22
  • 79
  • 154
  • is a script possible? for example, a script brute-force iterate over all ordering and output the ordering with the minimum space? – qqibrow Jan 12 '15 at 21:49
  • Not really...you can't iterate over a structs members in C unless the exact content of the struct is known. If you know the content of a particular struct, it is possible, but you cannot create a script that will work on all structs in general...does that answer your question? – buydadip Jan 12 '15 at 22:08
  • 1
    yeah. Just a little disappointed that there is no better way to do it. – qqibrow Jan 13 '15 at 19:03