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