Hacker News new | ask | show | jobs
by ernstsson 5096 days ago
Normally compilers does not do optimization of function calls between files anyway, so in this specific case that wouldn't matter. Within the same file it would've been different of course, bringing us to the second point; Yes, in this simplified example it's really very silly to have two files at all. The code itself isn't bad, just badly abstracted. The best refactoring for this limited problem would of course be to combine the files, but then the description of how to invert dependencies would've been lost. The cost of having examples easy to grasp in a short blog post I guess.
2 comments

> Normally compilers does not do optimization of function calls between files anyway, so in this specific case that wouldn't matter.

This is why function pointers are poison to the optimizer. There can be a 10-100x perf difference between C qsort and C++ std::sort because the use of that function pointer kills performance but in the C++ case the sort function is a template in a header file and can be inlined and then further optimized.

Thankfully, all major C compilers have at least some link time optimization efforts going on. When link time optimization becomes more widely available, we can finally stop thinking about translation units and use function pointers as much as we like.

So as a summary to the comments above; Function pointers between files isn't bad for performance if we can't do link time optimization. When link time optimization really becomes widely available, it's still not bad? Just the step in the middle that could be affected then? Thinking out loud here, any thoughts on this? I usually opt for structure over performance before profiling proves otherwise, but I still find this to be an interesting topic.
> So as a summary to the comments above; Function pointers between files isn't bad for performance if we can't do link time optimization.

No. Function pointers between files are horrible for performance. Do not use them if you're on the fast path. A function pointer (across translation units) not only destroys the compiler's ability to optimize, it also kills your cpu's instruction cache. You can solve the problem by using inline functions and apply __attribute__((always_inline)) or similar if required. If in doubt, check the assembly output of your compiler to verify that all calls have been inlined.

Link time optimization is the cure. It's not widely available at the moment, but maybe in a few years it will be more important. If you work in a relatively isolated piece of software, it's possible that you can use a compiler with link time optimization and get the perf gains today.

Meanwhile, don't use function pointers across translation units if you know you're on the fast path. If you're optimizing something that is profiled to be slow, look for function pointers because getting rid of them can give a big boost.

> I usually opt for structure over performance before profiling proves otherwise, but I still find this to be an interesting topic.

You should always go for structure over performance except when you should not.

FYI GCC and LLVM both do whole program optimisation these days. Not that this is going to help you with function pointers of course :)