Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Function pointer make the program slow?

I read about function pointers in C. And everyone said that will make my program run slow. Is it true?

I made a program to check it. And I got the same results on both cases. (measure the time.)

So, is it bad to use function pointer? Thanks in advance.

To response for some guys. I said 'run slow' for the time that I have compared on a loop. like this:

int end = 1000; int i = 0;  while (i < end) {  fp = func;  fp (); } 

When you execute this, i got the same time if I execute this.

while (i < end) {  func (); } 

So I think that function pointer have no difference of time and it don't make a program run slow as many people said.

like image 961
drigoSkalWalker Avatar asked Mar 13 '10 13:03

drigoSkalWalker


People also ask

What is the advantage of using function pointer?

1) Unlike normal pointers, a function pointer points to code, not data. Typically a function pointer stores the start of executable code. 2) Unlike normal pointers, we do not allocate de-allocate memory using function pointers. 3) A function's name can also be used to get functions' address.

Are function pointers safe?

Pointers to member functions in C++ This is how C++ uses function pointers when dealing with member functions of classes or structs. These are invoked using an object pointer or a this call. They are type safe in that you can only call members of that class (or derivatives) using a pointer of that type.


2 Answers

You see, in situations that actually matter from the performance point of view, like calling the function repeatedly many times in a cycle, the performance might not be different at all.

This might sound strange to people, who are used to thinking about C code as something executed by an abstract C machine whose "machine language" closely mirrors the C language itself. In such context, "by default" an indirect call to a function is indeed slower than a direct one, because it formally involves an extra memory access in order to determine the target of the call.

However, in real life the code is executed by a real machine and compiled by an optimizing compiler that has a pretty good knowledge of the underlying machine architecture, which helps it to generate the most optimal code for that specific machine. And on many platforms it might turn out that the most efficient way to perform a function call from a cycle actually results in identical code for both direct and indirect call, leading to the identical performance of the two.

Consider, for example, the x86 platform. If we "literally" translate a direct and indirect call into machine code, we might end up with something like this

// Direct call do-it-many-times   call 0x12345678  // Indirect call do-it-many-times   call dword ptr [0x67890ABC] 

The former uses an immediate operand in the machine instruction and is indeed normally faster than the latter, which has to read the data from some independent memory location.

At this point let's remember that x86 architecture actually has one more way to supply an operand to the call instruction. It is supplying the target address in a register. And a very important thing about this format is that it is normally faster than both of the above. What does this mean for us? This means that a good optimizing compiler must and will take advantage of that fact. In order to implement the above cycle, the compiler will try to use a call through a register in both cases. If it succeeds, the final code might look as follows

// Direct call  mov eax, 0x12345678  do-it-many-times   call eax  // Indirect call  mov eax, dword ptr [0x67890ABC]  do-it-many-times   call eax 

Note, that now the part that matters - the actual call in the cycle body - is exactly and precisely the same in both cases. Needless to say, the performance is going to be virtually identical.

One might even say, however strange it might sound, that on this platform a direct call (a call with an immediate operand in call) is slower than an indirect call as long as the operand of the indirect call is supplied in a register (as opposed to being stored in memory).

Of course, the whole thing is not as easy in general case. The compiler has to deal with limited availability of registers, aliasing issues etc. But is such simplistic cases as the one in your example (and even in much more complicated ones) the above optimization will be carried out by a good compiler and will completely eliminate any difference in performance between a cyclic direct call and a cyclic indirect call. This optimization works especially well in C++, when calling a virtual function, since in a typical implementation the pointers involved are fully controlled by the compiler, giving it full knowledge of the aliasing picture and other relevant stuff.

Of course, there's always a question of whether your compiler is smart enough to optimize things like that...

like image 112
AnT Avatar answered Sep 21 '22 18:09

AnT


I think when people say this they're referring to the fact that using function pointers may prevent compiler optimizations (inlining) and processor optimizations (branch prediction). However, if function pointers are an effective way to accomplish something that you're trying to do, chances are that any other method of doing it would have the same drawbacks.

And unless your function pointers are being used in tight loops in a performance critical application or on a very slow embedded system, chances are the difference is negligible anyway.

like image 23
Tyler McHenry Avatar answered Sep 19 '22 18:09

Tyler McHenry