views:

106

answers:

4

Are there any performance penalties when I use multiple nested structures/classes (kinda like using muti dimension heap arrays) or is it just an organizational feature of the language to make it easier to keep track of data and the compiler doesn't actually see any difference?

Thanks

+1  A: 

There shouldn't be any performance or memory penalties. They are just syntactic sugar to make things easier for the programmer.

Daniel A. White
+3  A: 

Not really. Classes/structs are just defining offsets into memory, so if you have a class within a class within a class, the compiler just adds up the offsets.

Performance comes into play once you have pointers (each pointer dereference is a memory read and potential L2 cache miss) or virtual functions (very bad, especially on older CPUs).

EDIT: One thing I should note though - if you're developing an application where performance is not absolutely crucial, focus on good class design rather than performance. While things like L2 cache misses make a big difference when you're writing something that needs to run at 60fps, it is of little relevance in a normal desktop application.

EboMike
So Pointers come at a penalty?
vol7ron
Deferencing them does. pA->pB->pC->pD will force the system to read from four addresses. Each one could be in a different cache page and cause an expensive L2 cache miss. Since you have do deference pA to find out pB, you won't be able to prefetch. However: Pointers are useful to keep rarely-used data away from the main struct, so if you have an array of structs that you need to iterate through a lot, keep the actual data you use in the struct and all the rarely-used stuff in a separate class/struct so that you need to fetch fewer cache pages.
EboMike
Virtual function calls are just one or two memory dereferences to get the function address out of the vtable, and then a function call. The performance is not significantly worse than, for example, a structure with a function pointer in C. And structures such as that are *everywhere* in the linux kernel.
SoapBox
Virtual function calls (as well as function pointer calls) can also not be predicted on older CPUs, that's another performance hit on top of the potential L2 cache miss. In general - if you don't need something to be virtual (or a callback), then don't do it that way. But again - keep the edit I made to my answer in mind. Don't write terrible code just for an unmeasurable performance gain.
EboMike
A: 

Short answer: No.

Pavel Radzivilovsky
+1  A: 

Mostly no, as others have mentioned. However, there's a small exception: Putting structs within structs can cause a small memory usage penalty due to alignment issues, relative to the same primitives being put directly in a single struct. This can in theory cost cache misses, which hurt performance. For example:

#include <iostream>
using namespace std;  // So sue me

struct A {
    double d;
    int i;
};

struct B {
    int j;
    int k;
    int l;
};

struct AB {
    A a;
    B b;
};

struct C {
    double d;
    int i;
    int j;
    int k;
    int l;
};

int main() {
    cout << sizeof(AB) << endl;  // 32
    cout << sizeof(C) << endl;   // 24
}
dsimcha
Will compiler optimizations deal with this? It looks almost like an inline type optimization.
Faken
Compiler optimizations can't deal with this because the layout of structs is part of the ABI and needs to be well-specified.
dsimcha