If there's function that takes a pointer to struct
as parameter and the function has a loop that access a member at every iteration like:
int function_a(struct b *b)
{
// ... do something then
for(int i = 0; i < 500; ++i){
b->c->d[i] = value();
}
}
Is it going to retrieve the location c points to and d points to from memory every time?
Now consider the following situation:
int function_a(struct b *b)
{
// ... do something then
float *f = b->c->d;
for(int i = 0; i < 500; ++i){
f[i] = value();
}
}
Would that be faster?
Faster and more efficient code can be written because pointers are closer to the hardware. That is, the compiler can more easily translate the operation into machine code. There is not as much overhead associated with pointers as might be present with other operators.
Array in C is used to store elements of same types whereas Pointers are address varibles which stores the address of a variable. Now array variable is also having a address which can be pointed by a pointer and array can be navigated using pointer.
It's much faster and memory-efficient to copy a pointer than to copy many of the things a pointer is likely to point to. A reference is stored in as many bytes as required to hold an address on the computer. This often makes reference much smaller than the things they refer to.
If you have a pointer (or a reference) to data, then you have two levels of memory access. First to load an address from the pointer (or reference) and then second to actually load the data. If you simply directly reference a variable, there is only one level of memory access. So here, a variable is faster.
I urge you to heed Thomas Matthews' advice regarding profiling, however to answer your question: it depends.
This particular transformation is also known as code hoisting which consists in moving code without side-effect and with the same result at each call outside of a loop. As noted though, this is only performed if the compiler can prove:
In both cases, this basically means that the compiler should have access to the full code (see the definitions) of both:
Therefore, it is actually unlikely that it will perform the optimization unless all the code for the body loop is included in the headers (and thus can be inlined) because any opaque function could hide a modification of b->c
(for example) through an evil global variable.
In your example, nothing proves that value()
does not change b->c
... so no, the compiler would be wrong to hoist the code unless it has access to the definition of value()
and can rule this possibility out.
Using a temporary may not be faster than accessing a temporary: depends on the platform.
When in doubt, look at the assembly language generated by the compiler. On the ARM processor, when accessing the memory:
This is very similar to dereferencing a pointer:
There may be a second load from memory to fetch the pointer value. The truth is in the assembly language.
This is known as a micro-optimization and should only be applied as a last resort to speed up code in performance critical areas. Use a profiler to find out where the bottlenecks are and address those first.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With