Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #10459 > unrolled thread

Virtual function call optimization

Started bycppquester <cppquester@googlemail.com>
First post2011-09-25 05:42 -0700
Last post2011-09-25 22:58 +0900
Articles 14 — 7 participants

Back to article view | Back to comp.lang.c++


Contents

  Virtual function call optimization cppquester <cppquester@googlemail.com> - 2011-09-25 05:42 -0700
    Re: Virtual function call optimization Leigh Johnston <leigh@i42.co.uk> - 2011-09-25 14:45 +0100
    Re: Virtual function call optimization Victor Bazarov <v.bazarov@comcast.invalid> - 2011-09-25 09:46 -0400
      Re: Virtual function call optimization cppquester <cppquester@googlemail.com> - 2011-09-25 20:24 -0700
        Re: Virtual function call optimization Victor Bazarov <v.bazarov@comcast.invalid> - 2011-09-26 08:51 -0400
          Re: Virtual function call optimization cppquester <cppquester@googlemail.com> - 2011-09-26 07:38 -0700
            Re: Virtual function call optimization "Kevin P. Fleming" <news@kpfleming.us> - 2011-09-26 09:59 -0500
              Re: Virtual function call optimization cppquester <cppquester@googlemail.com> - 2011-09-26 08:43 -0700
                Re: Virtual function call optimization Paavo Helde <myfirstname@osa.pri.ee> - 2011-09-26 11:51 -0500
                  Re: Virtual function call optimization cppquester <cppquester@googlemail.com> - 2011-09-26 11:25 -0700
                    Re: Virtual function call optimization Paavo Helde <myfirstname@osa.pri.ee> - 2011-09-26 14:48 -0500
                  Re: Virtual function call optimization Richard Damon <news.x.richarddamon@xoxy.net> - 2011-09-26 19:42 -0400
                    Re: Virtual function call optimization Miles Bader <miles@gnu.org> - 2011-09-27 13:47 +0900
    Re: Virtual function call optimization Miles Bader <miles@gnu.org> - 2011-09-25 22:58 +0900

#10459 — Virtual function call optimization

Fromcppquester <cppquester@googlemail.com>
Date2011-09-25 05:42 -0700
SubjectVirtual function call optimization
Message-ID<55363b39-cfd1-4ec2-be5a-fa180c64c557@f6g2000vbm.googlegroups.com>
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

[toc] | [next] | [standalone]


#10462

FromLeigh Johnston <leigh@i42.co.uk>
Date2011-09-25 14:45 +0100
Message-ID<QoednVqDWI_yreLTnZ2dnUVZ8sadnZ2d@giganews.com>
In reply to#10459
On 25/09/2011 13:42, cppquester wrote:
> 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

Depends if your compiler's optimizer is clever enough; typically they 
are clever enough to determine that dynamic dispatch is not required in 
certain cases.

/Leigh

[toc] | [prev] | [next] | [standalone]


#10464

FromVictor Bazarov <v.bazarov@comcast.invalid>
Date2011-09-25 09:46 -0400
Message-ID<j5nbba$rhs$2@dont-email.me>
In reply to#10459
On 9/25/2011 8:42 AM, cppquester wrote:
> 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
-- 
I do not respond to top-posted replies, please don't ask

[toc] | [prev] | [next] | [standalone]


#10497

Fromcppquester <cppquester@googlemail.com>
Date2011-09-25 20:24 -0700
Message-ID<82c6cb18-21af-47c3-9d68-60cfc58121b6@k34g2000yqm.googlegroups.com>
In reply to#10464
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.

[toc] | [prev] | [next] | [standalone]


#10515

FromVictor Bazarov <v.bazarov@comcast.invalid>
Date2011-09-26 08:51 -0400
Message-ID<j5psg0$pgl$1@dont-email.me>
In reply to#10497
On 9/25/2011 11:24 PM, cppquester wrote:
> 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
-- 
I do not respond to top-posted replies, please don't ask

[toc] | [prev] | [next] | [standalone]


#10517

Fromcppquester <cppquester@googlemail.com>
Date2011-09-26 07:38 -0700
Message-ID<f22d1a09-5f04-40f5-869e-6c43ab36e7c5@j10g2000vbb.googlegroups.com>
In reply to#10515
On 26 Sep., 18:51, Victor Bazarov <v.baza...@comcast.invalid> wrote:
> On 9/25/2011 11:24 PM, cppquester wrote:
>
> > Thank you all. Especially Miles.
> > Marc
>
> > @Victor:
> > Why do you answer if the question bothers you?
>
> Bothers?  Why do you think that?

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


> > 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?

So why criticizing me for asking?


>  > 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.

Please read on...


>  > 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.

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

[toc] | [prev] | [next] | [standalone]


#10518

From"Kevin P. Fleming" <news@kpfleming.us>
Date2011-09-26 09:59 -0500
Message-ID<4e80935c$0$31233$a8266bb1@newsreader.readnews.com>
In reply to#10517
On 09/26/2011 09:38 AM, cppquester wrote:

> 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.

[toc] | [prev] | [next] | [standalone]


#10519

Fromcppquester <cppquester@googlemail.com>
Date2011-09-26 08:43 -0700
Message-ID<d47cdff0-a16e-4bcc-bb28-476056e6a9a5@e9g2000vby.googlegroups.com>
In reply to#10518
On Sep 26, 8:59 pm, "Kevin P. Fleming" <n...@kpfleming.us> wrote:
> On 09/26/2011 09:38 AM, cppquester wrote:
>
> > 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.

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;
}


[toc] | [prev] | [next] | [standalone]


#10520

FromPaavo Helde <myfirstname@osa.pri.ee>
Date2011-09-26 11:51 -0500
Message-ID<Xns9F6CCA16CE458myfirstnameosapriee@216.196.109.131>
In reply to#10519
cppquester <cppquester@googlemail.com> wrote in news:d47cdff0-a16e-4bcc-
bb28-476056e6a9a5@e9g2000vby.googlegroups.com:

> 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


[toc] | [prev] | [next] | [standalone]


#10521

Fromcppquester <cppquester@googlemail.com>
Date2011-09-26 11:25 -0700
Message-ID<298aa576-d7d2-4644-8e1d-e3c69891575c@k17g2000yqi.googlegroups.com>
In reply to#10520
On Sep 26, 6:51 pm, Paavo Helde <myfirstn...@osa.pri.ee> wrote:
> cppquester <cppques...@googlemail.com> wrote in news:d47cdff0-a16e-4bcc-
> bb28-476056e6a...@e9g2000vby.googlegroups.com:
>
>
>
>
>
>
>
>
>
> > 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

[toc] | [prev] | [next] | [standalone]


#10524

FromPaavo Helde <myfirstname@osa.pri.ee>
Date2011-09-26 14:48 -0500
Message-ID<Xns9F6CE7FA9570Bmyfirstnameosapriee@216.196.109.131>
In reply to#10521
cppquester <cppquester@googlemail.com> wrote in
news:298aa576-d7d2-4644-8e1d-e3c69891575c@k17g2000yqi.googlegroups.com: 

> On Sep 26, 6:51 pm, Paavo Helde <myfirstn...@osa.pri.ee> wrote:
>> cppquester <cppques...@googlemail.com> wrote in
>> news:d47cdff0-a16e-4bcc- 
>> bb28-476056e6a...@e9g2000vby.googlegroups.com: 
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> > 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".

Ok, good to hear! I think you are right about interpreters.

In the above toy example the dynamic allocation would probably cost more 
than the virtual dispatch, I guess in your real application dynamic 
allocation (if any) does not happen so often.

Cheers
Paavo

[toc] | [prev] | [next] | [standalone]


#10529

FromRichard Damon <news.x.richarddamon@xoxy.net>
Date2011-09-26 19:42 -0400
Message-ID<j5r2lj$9r5$1@dont-email.me>
In reply to#10520
On 9/26/11 12:51 PM, Paavo Helde wrote:
> cppquester<cppquester@googlemail.com>  wrote in news:d47cdff0-a16e-4bcc-
> bb28-476056e6a9a5@e9g2000vby.googlegroups.com:
>
>> 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.

[toc] | [prev] | [next] | [standalone]


#10530

FromMiles Bader <miles@gnu.org>
Date2011-09-27 13:47 +0900
Message-ID<buod3emiobx.fsf@dhlpc061.dev.necel.com>
In reply to#10529
Richard Damon <news.x.richarddamon@xoxy.net> writes:

> 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

-- 
Accord, n. Harmony.

[toc] | [prev] | [next] | [standalone]


#10465

FromMiles Bader <miles@gnu.org>
Date2011-09-25 22:58 +0900
Message-ID<87litczptk.fsf@catnip.gol.com>
In reply to#10459
cppquester <cppquester@googlemail.com> writes:
> 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

-- 
Ich bin ein Virus. Mach' mit und kopiere mich in Deine .signature.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web