Sign in to follow this  
Alundra

inline virtual is a nonsense ?

Recommended Posts

In some sense the "inline" keyword itself is a nonsense.

 

"inline" only hint the compiler something should be inlined, but does not guarantee the compiler will do so. The compiler could also inline something else without that keyword.

 

Today's compiler think they are better than you and might completely disregard the keyword. And most of the time they are right.

Share this post


Link to post
Share on other sites

And most of the time they are right.

 

Nope, most of the time (if looking at distinct cases) they are wrong. They're still extremely dumb converters (despite all their necessary and respectable complexity). You just won't notice when they're wrong because the easy issues they solve are too easy to get wrong and the hard issues they try to solve usually don't matter.

 

If you were to build a virtual machine, you'd be surprised about the extents of compiler stupidity. They manage to completely disregard the needs of the instruction cache (at least that's what the measurements show by varying wildly between almost identical pieces of code), they don't know when inlining benefits the code and happen to be extremely conservative about it (unless it's extremely obvious, like with empty or very small functions, such as vector operators). But even if force-inlining a function, oddly enough, it sometimes performs worse than a preprocessor macro.

Edited by snake5

Share this post


Link to post
Share on other sites
The only purpose of "inline" is to allow you to break the one-definition-rule in C++. (As such, "templates" have implicitly defined "inline" as they are also allowed to break the ODR)

Compilers do not inline (or not inline) based on the presence (or absence) of the "inline" keyword. In fact, modern compilers can even inline functions defined only in C++ files at link-time. You pretty much can never control the compiler's inlining and it generally will do a much better job then you at deciding when to inline (or not inline).

To more directly answer your question, conceptually virtual calls have to have their destination chosen at runtime, so you cannot inline the code (because that would be choosing at compile time). In actuality, compilers can de-virtualize and then potentially inline as other posters have stated.

Share this post


Link to post
Share on other sites

The only purpose of "inline" is to allow you to break the one-definition-rule in C++. (As such, "templates" have implicitly defined "inline" as they are also allowed to break the ODR)

Compilers do not inline (or not inline) based on the presence (or absence) of the "inline" keyword. In fact, modern compilers can even inline functions defined only in C++ files at link-time. You pretty much can never control the compiler's inlining and it generally will do a much better job then you at deciding when to inline (or not inline).

To more directly answer your question, conceptually virtual calls have to have their destination chosen at runtime, so you cannot inline the code (because that would be choosing at compile time). In actuality, compilers can de-virtualize and then potentially inline as other posters have stated.

 

Also modern compilers do a pretty smashing job at in-lining things for you. If there is a virtual call that the compiler notices will never change, it will probably see if it can benefit from an inline or not. Kinda like noticing that you have a situation that's similar to 2^x, It will go ahead and swap that to a bitshift by x for you.

 

It's not always a guarantee that it will be inline. And usually, you will have to trust the compiler's judgement on it. It's been doing it's job longer than we have tongue.png.

No seriously, sometimes the compiler knows best.

Edited by Tangletail

Share this post


Link to post
Share on other sites


In some sense the "inline" keyword itself is a nonsense.

 

It has a completely different and very sensible purpose. Try putting a simple function or operator in a header used in multiple CPP files without the 'inline'.

Share this post


Link to post
Share on other sites




It has a completely different and very sensible purpose. Try putting a simple function or operator in a header used in multiple CPP files without the 'inline'.

 

It is still a nonsense because we only use it for its' side effect and not the original purpose. It should be something like

 

allow_duplicated_definition_and_assume_they_are_all_same void foo(){};

 

Nothing is actually inlined, why call it "inline"? The name only trick people to think it will "optymize" things, waste half a second to type and 7 bytes of precious disk space.

 

Newer languages don't even need the side effect of inline. Today's compilers are perfectly capable of knowing two definitions means exactly the same thing or not. They also don't use copy-and-paste based include so nothing is duplicated just because every source file must know about some source file.

 

Although this is the burden of an old language. It kind of surprised me that they decided the original meaning of "auto" is too silly to live in C++ anymore, but I think "inline" was used too much, and we will be stuck with it.

Share this post


Link to post
Share on other sites

It is still a nonsense because we only use it for its' side effect and not the original purpose. It should be something like
 
allow_duplicated_definition_and_assume_they_are_all_same void foo(){};
 
Nothing is actually inlined, why call it "inline"? [...]


I never thought it was misnamed. Initially I assumed that had something to do with me being a non-native English speaker but I did a few searches and both the dict.cc translation of 'inline' and a quick Wikipedia search suggests my language gut feeling was actually correct (Wikipedia suggests this for example as 'inline reply').

To me, that feels like a pretty canonical way of telling the compiler 'I'm just putting the whole thing here. And here. And there. So there might be a few duplicates'. As a matter fact, I cannot even think of a better keyword right now, 'allow_duplicated_definition_and_assume_they_are_all_same' is clearly too verbose and would make the code difficult to read.

That said, I wouldn't even care if it was slightly misnamed. Languages evolve. What was a good idea twenty years ago might not be today. Acoordingly, style, convention and usage slightly changes over time. If you cannot deal with that, you should not pick a thirty or forty year old language to begin with. But from my experience newer languages come with their own set of problems as well. Edited by BitMaster

Share this post


Link to post
Share on other sites

It is well named for it's original purpose, pasting code instead of the cost of a function call. That's is IF your compiler respects your decision, and they probably don't. They think they are too good to use your kind advice. Now the only use is to avoid the one definition rule, and it became misleading.

 

I'm also perfectly fine while using it (C++ is my main language). I just think that teachers/books should alert you it is likely that actual inlining will be done regardless of this. This keyword has almost nothing to do with performance today.

 

I also googled around for inlining in C#, and they have this [MethodImpl(MethodImplOptions.AggressiveInlining)]. Funny thing is .NET also only regard it as an hint. Compilers this day are all like "write assembly yourself or don't tell me what how I do my job".

Edited by AzureBlaze

Share this post


Link to post
Share on other sites

There are two big issues with that.

 

The first is that C# and C++ have radically different compilation models.

 

The second is that both C and C++ have several keywords that you could consider as advisory rather than compulsory. Inline is one of them. Register is another. Restrict is almost that way, but instead is a programmer's guarantee to the compiler that advises the compiler of a policy. The earlier version of auto is another, which fell out of use in the early 1980s. Being advisory is not a bad thing.

 

 

Dealing with the first one, the C# model, which is the same as Java and several other modern languages, is to have a shallow compile that includes everything. These languages build to an intermediate language and include all items, even those that the compiler has no visible need to include. This enables faster compiles and faster iteration, and enables language features like reflection where any code can use the compiled module and be certain it will all be available.  Contrast with the model used by C++ and C, along with many older languages, where elements are pruned and excluded, with vigorous eliding taking place.

 

One of the most obvious areas where this makes a difference is in the small accessor and mutator functions (also called "getters and setters").  Under the C and C++ model, you can have a set of nested calls that is ten, twenty, fifty, or even more layers deep. If all of them are available to the compiler at compilation, instead of emitting a series of nested function calls the compiler replaces it with a single direct access.  Try the same thing in C# or Java and the compiler won't inline it because the compiler does not look into the other files to see what they do. A series of accessors and mutators in these languages remains as a series of function calls, each incurring their function call cost. It might eventually be picked up as a hotspot at runtime, but it might not, and either way you are paying a very large cumulative cost at runtime rather than a large cost at compile time.

 

 

And on the second one, as mentioned above and in other posts, the inline keyword is still required in certain locations of code because of the compilation model. The other places it is used, it becomes and advisory to the compiler.   While the C# hint can be helpful to the compiler, due to the different compilation model it means something different. Similar with static functions, the compiler can use the knowledge to take certain optimizations that do not exist in other languages. In both cases the compiler (and the JIT compiler and hotspot compiler) can make better code because of it. 

Edited by frob

Share this post


Link to post
Share on other sites


Nothing is actually inlined, why call it "inline"? The name only trick people to think it will "optymize" things, waste half a second to type and 7 bytes of precious disk space.

 

Hmm, why would anybody ever put a function definition in a header file?

 

Maybe, I don't know... because they want it inlined?

 

I wonder what the keyword for that should be?

Share this post


Link to post
Share on other sites

Is it a nonsense having virtual function inlined ?

Absolutely not. Not every function call uses dynamic dispatch.  Any time a member function is called and the static type of its object is known at compile time, it is a candidate for inlining.  This turns out to be the majority of cases is much code.

 

It doesn't make much sense to have an inline function if the dynamic type of an object is not known until runtime.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this