[comp.lang.c++] >>> Virtual functions and inline ...

ssimmons@convex.com (Steve Simmons) (03/01/91)

>From: gas@cs.nott.ac.uk (Alan Shepherd)
> Organization: Nottingham University
> Date: 28 Feb 91 14:15:48 GMT
> Subject: Virtual functions and inline

> Is it okay to declare virtual functions inline ?  Even though the code
> to be excuted is substituted rather than a function call made, does
> the correct method still get called ?


	This is not a wise thing to do although the language will
	allow it.   

	In the first place, you are never guaranteed that a routine 
	is inlined. It is only a suggestion to the compiler.  If
	the routine is either too complicated or a virtual function,
	then a static copy of the routine will be placed in the 
	compiled module.   Thus, a routine that was coded as inline 
	may cause a performance degradation because it may consume
	much more space when it is not physically inlined.
	With a virtual function, a copy of that routine will be 
	created for every module that has at least one instantiation 
	of that class. 

	The language allows it but you would not be deriving any 
	better performance.  I have become very negative 
	towards the inline feature of a language like Ada's inline
	pragma or C++'s inline definition.  After all, inlining is 
	not part of the algorithm, just a performance enhancement. 
	Inlining should be done as part of the optimizing phase.

	Thank you. 


						Steve Simmons

mike@taumet.com (Michael S. Ball) (03/03/91)

In article <ssimmons.667836666@convex.convex.com> ssimmons@convex.com (Steve Simmons) writes:
>>From: gas@cs.nott.ac.uk (Alan Shepherd)
>> Organization: Nottingham University
>> Date: 28 Feb 91 14:15:48 GMT
>> Subject: Virtual functions and inline
>
>> Is it okay to declare virtual functions inline ?  Even though the code
>> to be excuted is substituted rather than a function call made, does
>> the correct method still get called ?
>
>	This is not a wise thing to do although the language will
>	allow it.   

Depending on your situation, it may be a very wise thing to do.  If
The compiler can compute the actual type of an expression at compile
time it can do the inline expansion.  One of the advantages of this is
the additional optimization which can be done because the exact
characteristics of the arguments are known.  Particularly when the use
is in a loop this can result in a very large performance increase.

>	In the first place, you are never guaranteed that a routine 
>	is inlined. It is only a suggestion to the compiler.  If

So what?  If it is inline you have the chance to win.  If it isn't,
you have lost very little.

>	the routine is either too complicated or a virtual function,
>	then a static copy of the routine will be placed in the 
>	compiled module.   Thus, a routine that was coded as inline 
>	may cause a performance degradation because it may consume
>	much more space when it is not physically inlined.

Possible, but unlikely in most situations.  The compiler should warn you
if it can't expand the function inline at all, and the other cases,
like taking a pointer to the function, are pretty rare.

>	With a virtual function, a copy of that routine will be 
>	created for every module that has at least one instantiation 
>	of that class. 

False.  A copy of that routine will be created whenever the compiler
has to create a virtual table.  This will usually be exactly once in the
entire program.

>	Inlining should be done as part of the optimizing phase.

True, but irrelevent.  Given that most compilers don't do this,
the user's question is how to make use of the facility which is provided.

The answer is to inline the function when:

	It is very short (shorter than the call, for example), or

	It is a bottleneck (better measure this)

Questions of virtualness are relatively unimportant.
-- 
Michael S. Ball			mike@taumet.com
TauMetric Corporation		(619)697-7607

jbuck@galileo.berkeley.edu (Joe Buck) (03/03/91)

In article <ssimmons.667836666@convex.convex.com>, ssimmons@convex.com (Steve Simmons) writes:
|[ Is it okay to declare virtual functions inline ? ]

!>      If
|> 	the routine is either too complicated or a virtual function,
|> 	then a static copy of the routine will be placed in the 
|> 	compiled module.   Thus, a routine that was coded as inline 
|> 	may cause a performance degradation because it may consume
|> 	much more space when it is not physically inlined.

Many implementations will do this, but all that's really necessary
is that the virtual function table have a pointer pointing to a
single copy of the virtual function.  If you can arrange to generate
only one copy of the virtual function table per class, then you
have no waste.

cfront 2.0 attempts to do this by a heuristic: generate the vtable
in the object module that contains the definition of the first
non-inlined virtual function.  This heuristic would work perfectly
except that functions can be declared inline outside the class body,
so there's more work (or more kludges) required to make the scheme
work.

As of 1.37.2, g++ introduced "#pragma interface" and "#pragma
implementation", a non-portable way of assuring that you only get
one vtable and one copy of inlined virtual functions per class.
There's been some discussion of implementing the cfront trick,
but this would make g++ virtual function calls as inefficient as
they are in cfront.

In an article in the C++ Journal describing the cfront scheme, the
authors quote the old chestnut "every problem in computer science
can be resolved by adding another level of indirection", and that's
precisely what they do -- in cfront you don't get a pointer to the
vtable in an object, you get a pointer to a pointer to the vtable.
Of course, you pay a cost for this on every function call.

|> 	With a virtual function, a copy of that routine will be 
|> 	created for every module that has at least one instantiation 
|> 	of that class. 

See above; not true in either cfront or in g++ (if you're willing
to use #pragma).

|> 	The language allows it but you would not be deriving any 
|> 	better performance.  I have become very negative 
|> 	towards the inline feature of a language like Ada's inline
|> 	pragma or C++'s inline definition.  After all, inlining is 
|> 	not part of the algorithm, just a performance enhancement. 
|> 	Inlining should be done as part of the optimizing phase.

Perhaps, but with separate compilation it's difficult to do inlining
as part of optimization.

Still, during development I think it's a good idea to avoid inlining
except for trivial one-liner functions.

--
Joe Buck
jbuck@galileo.berkeley.edu	 {uunet,ucbvax}!galileo.berkeley.edu!jbuck	

pcg@cs.aber.ac.uk (Piercarlo Grandi) (03/03/91)

On 1 Mar 91 14:11:06 GMT, ssimmons@convex.com (Steve Simmons) said:

From: gas@cs.nott.ac.uk (Alan Shepherd)

gas> Is it okay to declare virtual functions inline ?  Even though the
gas> code to be excuted is substituted rather than a function call made,
gas> does the correct method still get called ?

ssimmons> 	This is not a wise thing to do although the language
ssimmons> 	will allow it.

You can do it, and if your virtuals are usually resolvable at compile
time (because the class of the relevant object is known statically) they
will be inlined. Indeed this is a very frequent case, so it may well be
wise. In theory the compiler can generate an inline switch statement if
the virtual is not resolvable at compile time, but I know of no
compilers that do so.

ssimmons> 	In the first place, you are never guaranteed that a routine 
ssimmons> 	is inlined. It is only a suggestion to the compiler.  If
ssimmons> 	the routine is either too complicated or a virtual function,
ssimmons> 	then a static copy of the routine will be placed in the 
ssimmons> 	compiled module. [ ... ]

This need not happen with GNU C++, which has #pragma interface and
implementation, and does noit happen with recent versions of cfront 2.x
either (no direct experience), as it chooses one of the relevant objects
for dumping all the virtuals once and for all.

It used to happen, with horrid results, with cfront 1.x.
--
Piercarlo Grandi                   | ARPA: pcg%uk.ac.aber.cs@nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth        | UUCP: ...!mcsun!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk