Archived

This topic is now archived and is closed to further replies.

Russell

C++ structs vs. variables

Recommended Posts

Is there any overhead involved in stuffing a bunch of variables into a struct? For instance, if I had a bunch of variables: int a, b, c, d, e, f, g, h, i, j; and I wanted to put them into a struct to make it more mentally managable: struct foo { int a, b, c, d, e, f, g, h, i, j; };, is there now any overhead in accessing those variables? In other words, if I previously did this: SomeFunction(a); and now I do: SomeFunction(my_struct.a), is that any slower?

Share this post


Link to post
Share on other sites
Architect first, optimize later.
Even if it was slower, optimization should not come at the cost of organization and readability.

Share this post


Link to post
Share on other sites
What about if I have a lot of structs, or the structs are really big? Ex. my_struct.a.foo.bar.blah.erm.wut.huh I read that direct mode addressing only gives you a small range to work with. So there must be some overhead at some point, right?

Share this post


Link to post
Share on other sites
quote:
Original post by PlayGGY
Why does it matter? What are you making that you would need to worry about this?
These kinds of questions are just interesting to me. I also enjoy the "which one is faster, array[x][y] or array[y][x]?" discussions

Share this post


Link to post
Share on other sites
a.b.c.d.e.f.h and a.g are exactly the same speed. Here''s why.

Let''s suppose you have an int myInt on the stack (as a local variable). That means that in one of your registers is a stack pointer, and a certain (constant) offset up (or down, depending on architecture), is the beginning of your myInt. This offset is known at compile-time, since it''s just related to all the local variables you define. (In case you were wondering, this is why you used to have to define all your variables at the top of blocks in C). So when you want to, say, assign 3 to myInt, the computer does something like *(SP + 12) = 3, where 12 is the offset into the stack. If instead of myInt you have myStruct which has a struct which has a struct which has an int myOtherInt, etc, you still know--at compile time--where, relative to the stack pointer, myOtherInt is. So you can just change the offset, and you''re good to go.

What will change performance is if your struct stores, not structs, but pointers to structs, since those require extra run-time lookups. a->b->c->d->e->f is considerably slower than f.


"Sneftel is correct, if rather vulgar." --Flarelocke

Share this post


Link to post
Share on other sites
quote:
Original post by Sneftel
a.b.c.d.e.f.h and a.g are exactly the same speed. Here's why.

quote:
Original post by sjelkjd
it's exactly the same - the compiler knows the layout of the struct at compile time.
You don't know that, since it is totally up to the compiler. He never said which compiler and which platform he is using and neither did you.

There are cases on today's hardware with today's compilers where putting the variables into a struct would result in slower code.

[edited by - JohnBolton on April 3, 2004 3:47:36 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by JohnBolton
There are cases on today''s hardware with today''s compilers where putting the variables into a struct would result in slower code.

Like what? (not disbelieving, just interested)


"Sneftel is correct, if rather vulgar." --Flarelocke

Share this post


Link to post
Share on other sites
structs have layout order constraints that free variables don't. So if you're silly and declare a struct like:

struct A {
char a;
double b;
char c;
double d;
char e;
double f;
// ...
char yyyyyyy;
double zzzzzzz;
};

You'll probably have worse cache effects than if you declared the separate variables outside the struct (or if it the struct gets packed, bad alignment effects). This is, admittedly, a somewhat pathological case.

edit: formatting

[edited by - SiCrane on April 3, 2004 3:46:45 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Sneftel
quote:
Original post by JohnBolton
There are cases on today''s hardware with today''s compilers where putting the variables into a struct would result in slower code.

Like what? (not disbelieving, just interested)


Using a MIPS processor with GCC, there is a area of memory called the "small data section" where GCC puts smaller variables. There is a special addressing mode that accesses this area that is faster than other addressing modes. Putting those variables in a struct would move them out of the small data section and slow down the code.

Share this post


Link to post
Share on other sites
quote:
Original post by Captian Goatse
Structs suck. Speedwise you are always better off with unprotected globals, inline assembly and gotos.


Seems like a case of Carmack-itis

Share this post


Link to post
Share on other sites
quote:
Original post by SiCrane
structs have layout order constraints that free variables don''t. So if you''re silly and declare a struct like:

struct A {
char a;
double b;
char c;
double d;
char e;
double f;
// ...
char yyyyyyy;
double zzzzzzz;
};

You''ll probably have worse cache effects than if you declared the separate variables outside the struct (or if it the struct gets packed, bad alignment effects). This is, admittedly, a somewhat pathological case.



Is your example slow because it is integer and floating point variables intermixed, or because the size of the variables is alternated? For instance, is this also bad?


struct B {
unsigned char a;
unsigned long b;
unsigned char c;
unsigned long d;
// and so on...
};


Would this be better, to align them on 4-byte boundaries (assuming 32-bit processor)?


struct C {
unsigned long a;
unsigned long b;
unsigned long c;
unsigned long d;

unsigned char e;
unsigned char f;
unsigned char g;
unsigned char h;
};

Share this post


Link to post
Share on other sites
Yes, that would be better. Basically, certain datatypes on various architectures may need to be aligned to a particular memory offset. But since C++ compilers aren''t allowed to change the ordering of variables in a struct, they''re forced to add empty space between the variables, thus enlarging the struct.


"Sneftel is correct, if rather vulgar." --Flarelocke

Share this post


Link to post
Share on other sites
quote:
Original post by psamty10
quote:
Original post by Captian Goatse
Structs suck. Speedwise you are always better off with unprotected globals, inline assembly and gotos.


Seems like a case of Carmack-itis

Interestingly enough, I attended his talk at GDC and he was quite the opposite.

Share this post


Link to post
Share on other sites
quote:
Original post by Sneftel
But since C++ compilers aren''t allowed to change the ordering of variables in a struct


It''s not that C++ compiler can''t change the layout order inside of structs. The verbage actually goes: "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." (9.2 paragraph 12 in the C++ Standard) So if you declare no access specifiers in your struct (like in my example) then there''s no freedom of movement in the layout of the struct. If you declare every member with an access specifier, then the compiler has more elbow room (so to speak). Of course, if you do that, it uglifies the struct, and may not actually help to the same degree as getting the variables in the right order in the first place, or using variables outside of a struct.

On the other hand, it''s something you can take advantage of in some cases, like setting up DMZs for variables when working on a MP machine.

Share this post


Link to post
Share on other sites