0

If I have a structure containing an array of structures.... and on

config.data.item[3].userFunction();

is it better to access with

itemType * item = &config.data.item;

item[3].userFunction();
item[4].userFunction();

or is this just the same as

config.data.item[3].userFunction();
config.data.item[4].userFunction();

Or is there a limit to the number of levels where efficiency is lost, and does compiler optimisation have any effect?

Many thanks in advance for any insight offered.

Brian Campbell
  • 322,767
  • 57
  • 360
  • 340
  • personally, i think the second way is better. it depends on the compiler, but if you are care about efficiency, you should not write your code with assumption to the compiler. – Jason Hu Aug 22 '14 at 18:31
  • 1) the compiler will probably generate the same code. check it. 2) `item` can be directly accessed in `config.data.item`. there's *no indirection*. – Karoly Horvath Aug 22 '14 at 18:32
  • 1
    For my sanity, I almost always use a well-named intermediate variable when applicable. It is up to the compiler to worry about any such small optimizations it chooses to perform. (And even if it doesn't perform any such optimizations, and the program runs fast enough anyway - who cares? Not me.) – user2864740 Aug 22 '14 at 18:33
  • If the userFunction mutates the config, then the two versions are not equivalent. – hugomg Aug 22 '14 at 18:34
  • 1
    As with any of these types of questions, the best approach is to time it. I suspect that it may differ between compilers (and optimization settings), and I also suspect that any difference would be very very very small. Readability of code probably trumps any difference. – jeffrey_t_b Aug 22 '14 at 18:35
  • 1
    The only way to know for sure is to write up both and compare their performance. My gut tells me any difference will be insignificant, but you never know. Having said that, code for correctness first, then readability/maintainability. Don't sacrifice clarity of intent for a few cycles *unless* you're failing to meet a hard performance requirement. – John Bode Aug 22 '14 at 18:35
  • Place your compiled variations in any of ***[a variety of available open source disassemblers](http://reverseengineering.stackexchange.com/questions/1817/is-there-any-disassembler-second-to-ida)*** to best answer your question. – ryyker Aug 22 '14 at 18:36
  • 1
    @JohnBode Generally, you are right. But in this case, some low-level knowledge is sufficient to know that both variants should show exactly the same performance. "Should" because compilers *do* pretty insane stuff at times. – cmaster - reinstate monica Aug 22 '14 at 19:19

2 Answers2

1

Levels of indirection do have an impact, both in terms of CPU cycles and in readability. However, in your case there is only one level of indirection (the function pointer). Dot operator produces an offset to the location of config at compile time.

Regardless of this, creating a variable to hold the results of common sub-expression is a good idea, especially when you give that variable a meaningful name. In terms of CPU, however, you should see no impact: optimizing compilers are very good these days at detecting and optimizing common sub-expressions, so you should see the same performance either way you code this particular code fragment.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
-1

Even if you have do direct levels of indirection like a->b where there would be a potential cache and performance hit, even innocent looking a.b.c[x].d needs to be examined carefully as that [x] could very well push you out of the cache.

so the answer really is it depends what is in the cache, how big the cache is and what size of structures.

the only real way ever to tell is to test the code in the situation it will be used. You can't even test it in isolation as that would give you false results with cache utilization.

I guess in short, don't even worry about optimizing until you've tested and proven there is an issue and then see whether reorganizing struct fields or avoiding derefs helps...

Goblinhack
  • 2,859
  • 1
  • 26
  • 26