19
  • What is faster: Function pointers or switch?

The switch statement would have around 30 cases, consisting of enumarated unsigned ints from 0 to 30.

I could do the following:

class myType
{
    FunctionEnum func;
    string argv[123];
    int someOtherValue;
};
// In another file:
myType current;
// Iterate through a vector containing lots of myTypes
 // ... for ( i=0; i < myVecSize; i ++ )
    switch ( current.func )
    {
           case 1:
            //...
            break;
           // ........
           case 30:
             // blah
            break;
    }

And go trough the switch with func every time. The good thing about switch would also be that my code is more organized than with 30 functions.

Or I could do that (not so sure with that):

class myType
{
    myReturnType (*func)(int all, int of, int my, int args );
    string argv[123];
    int someOtherValue;
};

I'd have 30 different functions then, at the beginning a pointer to one of them is assigned to myType.

  • What is probably faster: Switch statement or function pointer?

Calls per second: Around 10 million. I can't just test it out - that would require me to rewrite the whole thing. Currently using switch.

I'm building an interpreter which I want to be faster than Python & Ruby - every clock cycle matters!

Rawr
  • 265
  • 1
  • 2
  • 5

4 Answers4

16

Switch statements are typically implemented with a jump table. I think the assembly can go down to a single instruction, which would make it pretty fast.

The only way to be sure is to try it both ways. If you can't modify your existing code, why not just make a test app and try it there?

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • 1
    Unless your compiler does a really bad job, switch will be at least as fast as function pointers. Using function pointers just picks one strategy for implementing switch, which is probably the best one and what the compiler would pick anyway, but with the overhead of parameter passing. The compiler might see a better way, esp. if any of the `case` bodies have any code in common. I'd be comfortable recommending the OP just use `switch`, and not waste his time trying both ways. It's safe to assume that switch will probably compile to good code. If it's a hotspot in profiling, check the asm. – Peter Cordes Sep 14 '15 at 19:19
5

I think the difference is negligible in most cases - your case might be an exception. Why don't you put together a simple prototype app to explicitly measure the performance of each solution? My guess is that it would not take more than an hour of work...

However, think about clarity and maintainability of the code as well. IMHO it is obvious that the function pointer solution wins hands down in this respect.

Update: Note also that even if one solution is, let's say, twice as fast as the other as it is, it still may not necessarily justify rewriting your code. You should profile your app first of all to determine how much of the execution time is actually spent in those switches. If it is 50% of total time, there is a reason to optimize it. If it is a couple of percents only, optimizing it would be a waste of effort.

Péter Török
  • 114,404
  • 31
  • 268
  • 329
  • The sole switch cases are only 10-20 lines long. Functions really wouldn't be more readable. It would take more than an hour to write this, probably one day - I don't have that much time. My question doesn't really depend on the architecture of my app - It is just function pointer vs switch performance at the lowest level. – Rawr Apr 18 '10 at 14:05
  • Sadly, you didn't tell me anything new: I should write two versions of my app to test it, impossible, and a prototype alone won't reflect the end-version of it well enough either. – Rawr Apr 18 '10 at 14:13
  • 1
    I may be completely missing something, but in my view the test app would need about 3 classes: an implementation of a single class method with a switch, another of same using function pointers, and a test class (or even a `main` method) which executes each method 10 million times and measures execution time. – Péter Török Apr 18 '10 at 14:15
  • I don't think it's clear that function pointers are favoured w.r.t clarity and maintainability. IMO function pointers are inferior unless you need the flexibility. If there is a (small) fixed set of valid continuations, a function pointer solution can not be honest about or enforce that. On the other hand having a switch of n cases, where each calls directly into another function, makes clear what can happen, and it's *not* a maintainability problem. – Jo So Sep 14 '16 at 19:29
3

Péter Török has the right idea about trying both and timing them. You may not like it, but unfortunately this is the reality of the situation. The "premature optimization" chant happens for a reason.

I'm always in favour of using performance best-practices right from the start as long as it doesn't sacrifice clarity. But in this kind of case it's not a clear win for either of the options you mentioned. In most cases, this kind of minor change will have no measurable effect. There will be a few major bottlenecks that completely govern the speed of the whole system. On modern computers a few instructions here and there will be basically invisible because the system is blocked by memory cache misses or by pipeline stalls and those can be hard to predict. For instance in your case, a single extra cache miss would likely decide which method would be slower.

The real-world solution is to evaluate the performance of the whole system with a profiler. That will show you where your "hot spots" are in the code. The usual next step is to make algorithmic changes to reduce the need for that many calls into the hot code either through better algorithms or through caching. Only if a very tiny section of code is lighting up the profiler is it worth getting down to small micro-optimizations like this. At that point, you have to try different things and test the effect on speed. Without measuring the effect of the changes, you're just as likely to make it worse, even for an expert.

All that being said, I would guess that function calls in your case might be very slightly faster if they have very few parameters, especially if the body of each case would be large. If the switch statement doesn't use a jump table, that likely be slower. But it would probably vary a lot by compiler and machine architecture, so I wouldn't spend much time on it unless you have hard evidence later on that it is a bottleneck to your system. Programming is as much about re factoring as it is about writing fresh code.

Alan
  • 4,897
  • 2
  • 24
  • 17
  • Good comments, Alan, but the very concept of "hot spot" is one that troubles me. It seems to come from the old idea that if too much time is being spent, the only way it can be overspent is by the PC register spending too much time in certain places that need to be changed. It's incredibly easy to fool any profiler based on that concept, and call graphs aren't much better. http://stackoverflow.com/questions/1777556/alternatives-to-gprof/1779343#1779343 – Mike Dunlavey Apr 18 '10 at 20:38
0

Writing interpreters is fun, isn't it? I can guess that the function pointer might be quicker, but when you're optimizing, guesses won't take you very far.

If you really want to suck every cycle out of that beast, it's going to take multiple passes, and guesses aren't going to tell you what to fix. Here's an example of what I mean.

Community
  • 1
  • 1
Mike Dunlavey
  • 40,059
  • 14
  • 91
  • 135