Virtual function call optimization

C

cppquester

Suppose I have:

class B
{
public:
virtual void foo() {}
}
class D: public B
{
public:
void foo() {}
}
int main(int argc, char *argv[])
{
D* d = new D();
d->foo();
return 0;
}

Will foo() be called using late binding or like a regular function
call?

Thanks in advance
Marc
 
V

Victor Bazarov

Suppose I have:

class B
{
public:
virtual void foo() {}
}
class D: public B
{
public:
void foo() {}
}
int main(int argc, char *argv[])
{
D* d = new D();
d->foo();
return 0;
}

Will foo() be called using late binding or like a regular function
call?

I'd venture a guess that it would be called like a regular function, but
only if your compiler is smart enough to recognize that. In any case
you can check it yourself by looking at the assembly code instead of
*asking us*. There is no requirement in the Standard that says one way
or the other.

V
 
M

Miles Bader

cppquester said:
class B { public: virtual void foo() {} };
class D: public B { public: void foo() {} }
int main () { D* d = new D(); d->foo(); }

Will foo() be called using late binding or like a regular function
call?

It depends. The compiler is allowed to do either.

Since the compiler can see the exact type of d in the above code, many
compilers are able to optimize the call to foo into a normal function
call, and even inline it, but other compilers will still call through
the vtable.

A quick check of some compilers installed here:

g++ 4.4 calls through vtable
g++ 4.5 calls through vtable
g++ 4.6 direct call (but doesn't inline)
g++ trunk direct call (can inline)
clang++ 2.9 direct call (can inline)
clang++ trunk direct call (can inline)

-Miles
 
C

cppquester

Thank you all. Especially Miles.
Marc

@Victor:
Why do you answer if the question bothers you?
Yes, I could have looked into the assembly code, but my project runs
on a variety of platforms. I do not have them all available all the
time and I wanted to know for more platforms than the ones I do have
available right now.
Therfore I think it was completely ok to ask here. I see you sometimes
criticizing people for asking something you think they should find out
themselves. Maybe you should be more careful with that. In the end I
could probably find out the answer to any question myself. It is just
a matter of effort. To save this effort I ask. This is IMHO one of the
ideas of the usenet.
 
V

Victor Bazarov

Thank you all. Especially Miles.
Marc

@Victor:
Why do you answer if the question bothers you?

Bothers? Why do you think that?
Yes, I could have looked into the assembly code, but my project runs
on a variety of platforms. I do not have them all available all the
time and I wanted to know for more platforms than the ones I do have
available right now.
Therfore I think it was completely ok to ask here.

Did I say it wasn't?
I see you sometimes
criticizing people for asking something you think they should find out
themselves.

So? It's my *right* to criticize anybody for anything. It's my
*opinion* and I am *entitled* to having it and expressing it.
Maybe you should be more careful with that.

No, I don't think so.
In the end I
could probably find out the answer to any question myself.

Yet you didn't.
It is just
a matter of effort. To save this effort I ask. This is IMHO one of the
ideas of the usenet.

No, that's not "one of the ideas of the usenet". The idea of usenet is
to conjure help where you are *unable* to find the answer or don't even
know the direction in which to look.

When you ask somebody else about something you can *easily* (like in
this case) find out by yourself, you essentially show that "saving your
own effort" by making others do the work for you is OK. Well, it isn't.
My *firm* belief is that converting USEnet into ABUSEnet, you stop
exercising your *brain* and instead exercise your typing fingers.
That's the real problem, and I simply *pointed it out to you*.

I suspect that your tone and your decision to give me shit for how I
replied, shows that in reality you *are aware* that your actions are
questionable and the fact that I pointed it out simply hit the nerve
that was already giving you discomfort. Well, learn your lesson and
move on.

Good luck!

V
 
C

cppquester

Bothers? Why do you think that?

We getting completely OT, but as you ask:
Because you complaint that I ask.

Did I say it wasn't?

So why criticizing me for asking?

So? It's my *right* to criticize anybody for anything. It's my
*opinion* and I am *entitled* to having it and expressing it.


No, I don't think so.

Please read on...

Yet you didn't.

Maybe it was not clear what I meant with effort:
If the effort is to organize a couple of platforms, install several
compilers, etc.
something in the order of many hours: Why not just ask instead?
Somebody might have done it already and is willing to share his
knowledge.

No, that's not "one of the ideas of the usenet". The idea of usenet is
to conjure help where you are *unable* to find the answer or don't even
know the direction in which to look.
When you ask somebody else about something you can *easily* (like in
this case) find out by yourself, you essentially show that "saving your
own effort" by making others do the work for you is OK. Well, it isn't.
My *firm* belief is that converting USEnet into ABUSEnet, you stop
exercising your *brain* and instead exercise your typing fingers.
That's the real problem, and I simply *pointed it out to you*.

I pointed out above that it would not have been as easy as you imply.
You put it as I want others to do my work. But I think here it would
have been maybe three or more hours (*) of my time vs. five minutes
for the answerer (if he already knew the answer - I would not expect
anybody to do research just to answer me).
Another time it might be vice versa: Overal a win win situation,
thanks to usenet.

(* in fact my project even runs on platforms I do not have access to
at all, where some contributers did the porting)

I suspect that your tone and your decision to give me shit for how I
replied, shows that in reality you *are aware* that your actions are
questionable and the fact that I pointed it out simply hit the nerve
that was already giving you discomfort. Well, learn your lesson and
move on.

(I could now cite somebody (-:
"It's my *right* to criticize anybody for anything. It's my
*opinion* and I am *entitled* to having it and expressing it.")

But it was for sure not my intention "to give you shit". I am sorry if
it came over that way.
I just wanted to let you know that IMHO your critics are not always
justified. And for sure not here.

Let me add that I respect you due to your activity and the good
quality of your replies in this NG.
You helped a lot of people, including me. Thank you and please
continue to do so.

Good luck!
Same to you!

Marc
 
K

Kevin P. Fleming

Maybe it was not clear what I meant with effort:
If the effort is to organize a couple of platforms, install several
compilers, etc.
something in the order of many hours: Why not just ask instead?
Somebody might have done it already and is willing to share his
knowledge.

But that's not the question you asked: you didn't specify any platforms,
compilers or anything else. You asked a generic question about C++.

If you had said "I've tested this on Windows using Visual Studio 2010
and Ubuntu 11.04 using gcc 4.5.1, but I need to know if it will be
optimized on platforms X, Y and Z" the answers to your question would
have been very different.
 
C

cppquester

But that's not the question you asked: you didn't specify any platforms,
compilers or anything else. You asked a generic question about C++.

If you had said "I've tested this on Windows using Visual Studio 2010
and Ubuntu 11.04 using gcc 4.5.1, but I need to know if it will be
optimized on platforms X, Y and Z" the answers to your question would
have been very different.

Yes, it would have been: "Ask in a platform specific group" :)
Which would have been ok, but I was expecting that it is clearly
defined (to use a regular function call).
Or at least a de facto standard.

But as at least on some platforms late binding is used I found a
solution (for all platforms):

class B
{
public:
virtual void foo() {}
};

class D: public B
{
public:
void foo() { fooD();}
void fooD() {}
};

int main(int argc, char *argv[])
{
D* d = new D();
d->fooD();
return 0;
}
 
C

cppquester

(e-mail address removed):








But as at least on some platforms late binding is used I found a
solution (for all platforms):
class B
{
public:
virtual void foo() {}
};
class D: public B
{
public:
void foo() { fooD();}
void fooD() {}
};
int main(int argc, char *argv[])
{
D* d = new D();
d->fooD();
return 0;
}

Just out of curiosity (as this gets discussed pretty often), how much did
avoiding this virtual call make your application faster? (I mean your
real application with realistic usage pattern and data, not the empty
example function here). How many percents did the slow operation go
faster?

thanks
Paavo

The project is actually an interpreter. If I use an (interpreted)
program which makes heavy use of the code path I just changed to avoid
the late binding, it speed up about 10%, which I find quite
remarkable. My system did use late binding before.
I think interpreters are one of the few fields where "every cycle
counts".

Cheers,
Marc
 
R

Richard Damon

But as at least on some platforms late binding is used I found a
solution (for all platforms):

class B
{
public:
virtual void foo() {}
};

class D: public B
{
public:
void foo() { fooD();}
void fooD() {}
};

int main(int argc, char *argv[])
{
D* d = new D();
d->fooD();
return 0;
}

Just out of curiosity (as this gets discussed pretty often), how much did
avoiding this virtual call make your application faster? (I mean your
real application with realistic usage pattern and data, not the empty
example function here). How many percents did the slow operation go
faster?

thanks
Paavo

One spot where late binding can cost alot is that it prevents inlineing
of code. If foo was an assessor function, then this could be significant.

The key is that you must let the compiler know the static type of the
object (or make it so that it can deduce it), to eliminate the late-binding.

Using a none-virtual function connection is one way. Another way that
should work is making your call

d->D::foo();

Another method, if you are willing to upgrade to C++11, and the object
definition allows it, is to declair foo() to be final, as in

class B
{
virtual void foo() {}
};

class D: public B
{
public:
void foo() final ( ... }
}

since D::foo is final, late binding is not needed if the pointer has
static type D.
 
M

Miles Bader

Richard Damon said:
Another method, if you are willing to upgrade to C++11, and the object
definition allows it, is to declair foo() to be final, as in ....
class D: public B
{
public:
void foo() final ( ... }
}

since D::foo is final, late binding is not needed if the pointer has
static type D.

Or sometimes more conveniently, declaring the whole class D to be final:

class D final : public B
{
public:
void foo();
};

(which has the advantage that it will make all methods final, even those
D doesn't override)

-miles
 

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,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top