Pointer dereferencing overhead vs branching / conditional statements

穿精又带淫゛_ 提交于 2019-12-05 01:12:00

The function pointer approach let's you make the transitions asynchronous. Rather than just passing dt to the updater, pass the object as well. Now the updater can itself be responsible for the state transitions. This localizes the state transition logic instead of globalizing it in one big ugly if ... else if ... else if ... function.

As far as the cost of this indirection, do you care? You might care if your updaters are so extremely small that the cost of a dereference plus a function call overwhelms the cost of executing the updater code. If the updaters are of any complexity, that complexity is going to overwhelm the cost of this added flexibility.

I think I 'll agree with the non-believers here. The money question in this case is how is the pointer value going to be set?

If you can somehow index into a map and produce a pointer, then this approach might justify itself through reducing code complexity. However, what you have here is rather more like a state machine spread across several functions.

Consider that something_else_happens in practice will have to examine the previous value of the pointer before setting it to another value. The same goes for something_different_happens, etc. In effect you 've scattered the logic for your state machine all over the place and made it difficult to follow.

Now what I'm really wondering is: am I obsessing about this needlessly?

If you haven't actually run your code, and found that it actually runs too slowly, then yes, I think you probably are worrying about performance too soon.

Herb Sutter and Andrei Alexandrescu in C++ Coding Standards: 101 Rules, Guidelines, and Best Practices devote chapter 8 to this, called "Don’t optimize prematurely", and they summarise it well:

Spur not a willing horse (Latin proverb): Premature optimization is as addictive as it is unproductive. The first rule of optimization is: Don’t do it. The second rule of optimization (for experts only) is: Don’t do it yet. Measure twice, optimize once.

It's also worth reading chapter 9: "Don’t pessimize prematurely"

Testing a condition is:

  • fetch a value
  • compare (subtract)
  • Jump if zero (or non-zero)

Perform an indirection is:

  • Fetch an address
  • jump.

It may be even more performant!

In fact you do the "compare" before, in another place, to decide what to call. The result will be identical. You did nothign more that an dispatch system identical to the one the compiler does when calling virtual functions. It is proven that avoiding virtual function to implement dispatching through switches doesn't improve performance on modern compilers.

The "don't use indirection / don't use virtual / don't use function pointer / don't dynamic cast etc." in most of the case are just myths based on historical limitations of early compiler and hardware architectures..

The performance difference will depend on the hardware and the compiler optimizer. Indirect calls can be very expensive on some machines, and very cheap on others. And really good compilers may be able to optimize even indirect calls, based on profiler output. Until you've actually benchmarked both variants, on your actual target hardware and with the compiler and compiler options you use in your final release code, it's impossible to say.

If the indirect calls do end up being too expensive, you can still hoist the tests out of the loop, by either setting an enum, and using a switch in the loop, or by implementing the loop for each combination of settings, and selecting once at the beginning. (If the functions you point to implement the complete loop, this will almost certainly be faster than testing the condition each time through the loop, even if indirection is expensive.)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!