Reputation: 265
The switch statement would have around 30 case
s, 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.
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!
Upvotes: 19
Views: 14470
Reputation: 40669
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.
Upvotes: 0
Reputation: 4933
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.
Upvotes: 3
Reputation: 116266
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.
Upvotes: 5
Reputation: 308196
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?
Upvotes: 16