Reputation:
Is the process of accessing a struct member any slower than accessing a direct variable? If I have the same struct member used in multiple places, should I declare it in a variable and save it there to spare the cost of accessing the same member multiple times? Should I repeat Struct.Member
Struct.Member
Struct.Member
or should I save it in a variable int Member = Struct.Member
Member
Member
Member
? At which point should I use the latter instead of the former? What if those members are bit fields?
Upvotes: 8
Views: 2594
Reputation: 11
I can tell you that in using GNU C and writing code to a Cortex M33 using the highest available optimization setting, pulling a value out of an array before using it in a 'for' loop saved a few cycles. I would expect that the compiler treats a structure much like an array, so it probably would likewise speed things up, but very slightly.
The code I'm writing must execute AFAP so I measure everything. Measuring is probably the only way to know for sure. Beware when measuring code with high optimization settings though. If you test something where the result is going nowhere, the optimizer will often not bother running the inner loops. I use a scope and an IO pin to measure timing. Making the IO state depend on the result solves this problem... usually ;)
Upvotes: 0
Reputation: 224092
While there are some complications involving accessing a structure member versus allocating a “direct” object, a more important difference in your scenario is that a compiler may be able to better optimize uses of a local variable than uses of a member of a structure it is passed.
This is because structures are commonly passed indirectly, by a pointer (that is either a parameter or a pointer from another structure). Consider this code:
struct S { int a; };
void baz(int);
void foo(struct S *s)
{
baz(s->a);
baz(s->a);
}
void bar(struct S *s)
{
int a = s->a;
baz(a);
baz(a);
}
In bar
, the compiler knows that baz
cannot change a
, because a
is a local variable whose address is never taken. Therefore, the compiler can load s->a
from memory once and pass it to baz
twice.
In foo
, the compiler cannot know that baz
does not change s->a
, because baz
could have some way of accessing s->a
such as through an address stored in an external object. Therefore, it has to load s->a
before the first call to baz
and again between the first call and the second call.
Testing with Apple Clang 11.0.0 with optimization enabled confirms this; the assembly code generated for the foo
routine contains two loads of s->a
from memory, while the code for bar
contains only one.
Although this occurs frequently for structures since structures are commonly passed by address, this is not inherently a consequence of being a structure member. The same issue occurs in this code:
void baz(int);
void foo(int *p)
{
baz(*p);
baz(*p);
}
void bar(int *p)
{
int a = *p;
baz(a);
baz(a);
}
It can also occur even if no subroutine is called; parameters can “interfere” with other parameters. In the following code, foo
must reload z->a
but bar
does not need to. Even though z
is qualified with const
, the assignment to x
might change it:
struct S { int a; };
void foo(struct S *x, struct S *y, const struct S *z)
{
x->a = z->a;
y->a = z->a;
}
void bar(struct S *x, struct S *y, const struct S *z)
{
int a = z->a;
x->a = a;
y->a = a;
}
Upvotes: 6
Reputation: 214880
There is no reason why a struct member access would be slower than a plain variable.
There might be a few special case exceptions to that, like when you have a pointer to struct, and the compiler has to go through the pointer to get to the data. Then you get indirect access, which is generally a tiny bit slower than direct access. But micro-optimizations like that isn't something you should worry about when writing code.
Generally, focus on writing readable code and you usually get fast code at the same time. Beginners trying to manually optimize code and thereby turning it into an unholy mess is a common problem. Manual code optimization is very qualified work and not something you should be worrying about until you have some 10+ years of programming experience.
Upvotes: 3