Function pointers: performance penalty?

P

Phil Carmody

Seebs said:
That depends! Many modern systems, rather than "finding sequences of
printable characters", "find strings" -- meaning, for a file in a known
binary format, they will actually decode the headers and display all
of the symbols and string literals defined, regardless of length.

... Which, let me tell you, is a bit of a shock if you don't know about
it.

The fact that there could be strings which that approach misses would
annoy me greatly. Strings disappearing just because you changed
optimisation flags, for example.

Phil
 
P

Phil Carmody

Richard Heathfield said:
Not at all. All our violent disagreements and public spats are
carefully stage-managed and scripted via the cabal mailing list.
(TINC.)

E-mail's down - it now I hit you over the head with Plaugher, and you
shove burning pages of Shildt down my back, in which case I'll put on
my asbestos underwear?
Unlike apples, oranges are utterly irrelevant to the question of
universal gravitational attraction, so their weight doesn't enter
into it.

Initially I had thought of using 'apple' in the X-planation, but
my g/f persuaded me that apples were, alas, light, and thus would
most likely invoke "no, duh!" responses.

Phil
 
N

Nick Keighley

Seebs a écrit :

Interesting, very interesting.

All the research papers about this subject (and there are hundreds
of research papers in the literature on this subject)
are done by people that missed your point. Interesting really.

For instance:http://www.cs.ucsb.edu/~urs/oocsb/papers/oopsla96.pdf
The Direct Cost of Virtual Function Calls in C++

That is just nonsense research. All those papers that try to improve
the direct cost of virtual function calls are just wrong...

Incredible how much nonsense can be written here.

There are TWO costs associated with an indirect function call (i.e.
through a function pointer)

(1) The direct cost of pipeline problems as I described in my other
message
(2) The INDIRECT cost because the call graph is not explicit, what makes
many optimizations impossible. This second cost is often neglected but
it is very real.

isn't there also a cost to loading the function pointer in the first
place? Or are the x86 instructions clever enough to avoid this
somehow?

And I will forget about the nonsense of heathfield that tries to make
a distinction between assembler mnemonics and machine code,

that confused me too, though apparently modern assemblers are quite
"smart"
or even
kuyper that says that all function calls are pointer function calls
with some citation from the C standard...

technically he is correct though I don't see what it has to do with
the cost
of a function pointer.
(even saying that loading the
value of the call into the instruction pointer is a "pointer" call).

bizzare, I agree
 
J

James Kuyper

Seebs said:
I assumed "to calling a function by name the ordinary way".

As I and others have repeatedly pointed out, that's would be a useless
comparison. In any situation where the use of function pointers is
appropriate, "to call a function by name the ordinary way" is almost
never a complete alternative to calling it through the pointer. The
other things that you would have to change to achieve the same behavior
using direct function calls will have am impact on the performance of
the code that is at least comparable to, and possible greater than, the
impact of the difference in the function calling mechanism.
 
N

Nick Keighley

Phil Carmody a écrit :

I *think* I got the attributions right...

RM:
PC:
BC:
PC

so direct calls are faster than calls through function pointers
except when function pointers are faster


I've lost the context by this time

this seemed uncalled for. What is he assuming?

This person then, calls a constant value "a fixed pointer".

("this person" isn't a very polite way to refer to people in english)

to be fair the standard glibly treats "address" and "pointer" as the
same
thing. So TP is really saying that a constant *address* is a fixed
pointer. Which isn't quite so bizzare. Though I don't find the term
"fixed pointer" very helpful or useful in this context.

When I use
a call instruction, the offset to the start of the called function is
an immediate number embedded in the instruction stream. For this
person this is "a fixed pointer"...

When I write
        int a = 543;

then, with the same logic, I am assigning a pointer to an integer,
since 543 is a "fixed pointer". Strange that the compiler doesn't
complain.

543 isn't an address (except for those who think addresses are
numbers).

Then, (as always) this person starts with insults:

"You are making ASSumptions"

of course that is not an insult to anybody... just , well, just
the caps lock key stuck.

ah, but responding in a similar manner doesn't help. Though it *is*
tempting...
<quote Antoninus>

never a bright idea

<snip>
 
N

Nick Keighley

Was it meaningful?

since I didn't understand it, no
Was it a direct analogue to the question asked?

dunno what's a "direct analogue"?, so mu
If you haven't answered "no, yes" in that order, then let's try a
non-computing analogue:

Subject: Oranges: heavier?
Are oranges heavy? If so, how much heavier are they?

here's a novel idea, why not just answer the question in plain english
or explain in PE why you think it is a poor question.

To me "is than an overhead to using function pointers" sounds a pretty
ok question. Yes there's all sorts of caveats and implementaion
specific
geegaws. But isn't clc actually here to address questions like that?
 
B

bartc

So my apparently meaningless initial answer wasn't there *just* to
get you to question the question (such as the way an answer of
nothing more than 'mu' might do, perhaps, or a more direct "what
would you be doing otherwise?"), but also to encourage you to
think why I deliberately chose what seemed to be exactly the
wrong answer if you barge through with all assumptions blazing
regarding the original question.

For what I use them for, function pointers /are/ faster*.

All very clever. But isn't it you now making assumptions as to the OP's
purpose?

If I'd replied to the OP, which I didn't, I would only have addressed the
obvious question, comparing ordinary function calls with those via explicit
pointers.

And maybe his choice /was/ between those two, we don't know. (Why would he
choose explicit calls if he could do direct calls instead? Well there are a
few cases where that could be considered, although to help make the
decision, it would be useful to know whether explicit pointers incur a
performance penalty...)
 
K

Keith Thompson

Phil Carmody said:
Why didn't you all challenge the OP equivalently?

Several people did. You even quote examples of Nick pointing out
the problem with the OP's question. He just did it more directly
than you did.

[...]
And what happened when Nick asked: [snip]
And what happens when he then re-iterates: [snip]
Nothing.

I think we all realized that the original question was incomplete,
when Nick pointed it out if not sooner. Nick's point was
sufficiently obvious that we didn't feel any need to comment on it,
thus the "Nothing" response.

Meanwhile, some of us tried to discuss what we reasonably thought
the OP meant: (does an indirect function call, via a pointer,
impose a performance penalty relative to an equivalent call using
the function's name direction?) -- as well as the question of whether
*that* question has any meaningful answer.

We are not restricted to answering the exact question the OP asked.
Irony apparently worked far better /in the long run/ than the simpler
more direct approach Nick adopted. More direct? It's about as straight
and direct as you can get, and yet it was apparently completely over-
looked! That's quite a negative thing to highlight about the readership
of c.l.c.

I don't think it was overlooked. As for your irony working better,
it was widely misunderstood and led to a long sub-thread that didn't
contribute much to the discussion.

Personally, when you wrote "Nope, function pointers are faster",
I seriously considered the possibility that you meant that indirect
calls are faster than equivalent indirect calls, and that you might
know something about it that I didn't.

[snip]
 
K

Keith Thompson

James Kuyper said:
As I and others have repeatedly pointed out, that's would be a useless
comparison.
[...]

Not necessarily.

Consider a programmer trying to choose between this:

if (condition) {
func0(42);
}
else {
func1(42);
}

and this:

void (*fptr)(int) = cond ? func0 : func1;
fptr(42);

If it's in an inner loop, knowing which is faster could be critical.
If there were some general rule that indirect function calls are
always much much slower than direct function calls, or even if they
were much slower on some platforms, the if statement would be the
obvious choice; otherwise, the indirect call might be clearer.

(This is a fairly trivial example, not intended to be an example
of well-written real-world code.)

As we've seen from this discussion, the standard says nothing about
performance, but on most systems the penalty for an indirect call,
if any, should be fairly small.

On the other hand, a direct call might provide more opportunities
for inlining and other optimizations.
 
J

jameskuyper

Keith said:
James Kuyper said:
As I and others have repeatedly pointed out, that's would be a useless
comparison.
[...]

Not necessarily.

Consider a programmer trying to choose between this:

if (condition) {
func0(42);
}
else {
func1(42);
}

and this:

void (*fptr)(int) = cond ? func0 : func1;
fptr(42);

My point is, that this is not simply a replacement of a call through a
pointer object by a direct call to the function itself; some of the
surrounding code had to be modified as well. This will always be true
in any context where using a function pointer was a reasonable thing
to do. The performance differences due to the other changes have to be
taken into consideration as well; they might easily exceed the
differences due to the change in the function call mechanism, and the
difference might have the opposite sign.

....
As we've seen from this discussion, the standard says nothing about
performance, but on most systems the penalty for an indirect call,
if any, should be fairly small.

Which is precisely why the other changes that must accompany that one
must also be taken into consideration, if one is micro-optimizing to
the point where that difference matters.
 
S

Seebs

As I and others have repeatedly pointed out, that's would be a useless
comparison. In any situation where the use of function pointers is
appropriate, "to call a function by name the ordinary way" is almost
never a complete alternative to calling it through the pointer. The
other things that you would have to change to achieve the same behavior
using direct function calls will have am impact on the performance of
the code that is at least comparable to, and possible greater than, the
impact of the difference in the function calling mechanism.

Imagine that you are in one of those circumstances, but that for some
historical reason, you have a tangle of macro definitions and such which
are used to provide the intended effect of function pointers; you might have
a ton of things using token pasting and so on to build names like
"read_from_dev0()" and "read_from_dev1()".

And someone says hey, why don't we just use function pointers, and do
something like "dev0->read()"?

And then someone says "because function pointers are expensive."

Or, alternatively, you have a bunch of dev0->read(), and someone suggests
the ugly thing with the macros because there's a performance problem.

In short, if there's a noticeable performance difference, there may be
cases in which it might be WORTH a substantial refactor to change things.

.... But that's true only if the difference is huge, and I'm betting that it's
not, but that people who are used to thinking in terms of C++ virtual
methods are thinking that function pointers are quite a lot more expensive
than regular calls.

-s
 
P

Phil Carmody

bartc said:
All very clever. But isn't it you now making assumptions as to the
OP's purpose?

If I am, please tell me what it is? (And the message id and line number
of where I first express it, please.)
If I'd replied to the OP, which I didn't, I would only have addressed
the obvious question, comparing ordinary function calls with those via
explicit pointers.

At the point of a call, even function names are explicit pointers in C,
for reference.
And maybe his choice /was/ between those two, we don't know. (Why
would he choose explicit calls if he could do direct calls instead?
Well there are a few cases where that could be considered, although to
help make the decision, it would be useful to know whether explicit
pointers incur a performance penalty...)

Only given some context, something to compare it to.

Examples where function pointers are faster than calls to functions
directly by name are trivial to come up with (computed targets).
Examples where the opposite is true are also trivial (messy
interfaces which can be inlined).

Phil
 
B

bartc

Phil Carmody said:
If I am, please tell me what it is? (And the message id and line number
of where I first express it, please.)

"
If I'm considering function pointers, I'm most likely not looking
at a scenario where direct calls to functions make much sense.
So _the comparison should surely not by default be against direct
calls to functions_ but to other mechanisms of selecting code paths
dynamically, such as switch statements, or echelons of ifs, or
whatever."

(My underline marks.)
At the point of a call, even function names are explicit pointers in C,
for reference.

That's a silly argument. It's like saying there's no difference between int,
int*, int** and so on, because at the point of access, they're all using the
address of the int value (and yes I understand that auto-dereferencing
applies to function pointers but not to int pointers, but we're looking
behind that mechanism).

I used the word "explicit" for a reason, to distinguish between functions,
and pointers to functions, as clc people seem to delight in demolishing
these differences.
Only given some context, something to compare it to.

I've often considered converting a bunch of like function calls into
table-driven code. The overheads of possible loops and arrays are
well-known, but what about calls via function pointers? Hence the topic of
this thread.
 
N

Nick Keighley

Given the importance of context, all bets are off, then.

there seem to be two sorts of poster. Those who post in order to
communicate
something and think clear and straightforward english with appropriate
context
is a good way to do this, and those who think posting is some sort
cryptography
challenge where you attempt to minimise the information leaked to the
enemy
(ie. everyone else).

You seem to be in the latter group.
 
R

Rui Maciel

jacob said:
This depends on the CPU, the deep of the pipeline (if any) and many other
things. If there is a pipeline, coupled with speculative execution, an
indirect jump will provoke a flush of the pipeline, since all instructions
after the indirect jump can't be known, unless the value of the jump is
loaded very early in the register, a,d the speculative execution machine
can determine it wont be affected by subsequent operations...

A call instruction has its destination embedded in the code stream. The
CPU will know it in advance and will know that it will not change. Using
that knowledge, it can start executing the call instruction in advance.

Within the context of lcc-win, i was forced to use ALWAYS for all function
calls ONLY indirect calls. This slowed down the code considerably, more
than 15-20%.

If you are using the indirect jump within a tight loop, it is better if
you could avoid it, but if you are using an indirect call anyway, it is
because of some reason, and that is not going to change and it is not
going to be replaced by something else.


Thanks, Jacob, for the insightful answer. Kudos.


Rui Maciel
 
B

bartc

Phil Carmody said:
Please learn some English. Please get as far as modals before
posting again.

No hints in your header this time as to what you're on about.

Your remarks seem to me to clearly indicate an assumption about the
circumstances in which the OP might want to use function pointers.

If it's necessary to learn some obscure points of grammar to discern some
alternative meaning, then you might want to learn to communicate more
effectively. But I suspect you just don't want to concede a point!
 
P

Phil Carmody

bartc said:
No hints in your header this time as to what you're on about.

No, because it's perfectly explicit within the body of the post.
Your remarks seem to me to clearly indicate an assumption about the
circumstances in which the OP might want to use function pointers.

So by beginning sentences "If I'm ..." you think I'm making assumptions
about someone else? If so, please learn some English.

Or are you instead conflating the concepts of
"making assumptions as to the OP's purpose"
and
"an assumption about the circumstances in which the OP might want to
use function pointers"
?
In which case, please learn some English - where did the "might want"
come from, for a start?
If it's necessary to learn some obscure points of grammar to discern
some alternative meaning, then you might want to learn to communicate
more effectively. But I suspect you just don't want to concede a point!

I suspect that you really don't understand how poor your comprehension
of English is.

Phil
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top