As an LLVM developer, I really wish the author filed a bug report and waited for some analysis BEFORE publishing an article (that may never get amended) that recommends not using this keyword with clang for performance reasons. I suspect there's just a bug in clang.
The Performance Impact of C++'s `final` Keyword
311–320 of 385 posts
Re: The Performance Impact of C++'s `final` Keyword
#312Earlier quoted context omitted.
In general the compiler/linker cannot assume that derived classes won't arrive later through a shared object. You can tell it "I won't do that" though with additional flags, like Clang's -fwhole-program-vtables, and even then it's not that simple. There was an effort in Clang to better support whole program devirtualization, but I haven't been following what kind of progress has been made: https://groups.google.com/g…
This optimization option isn't on by default? That sounds like a lot of missed optimization. Most programs aren't going to be loading from shared libraries. Maybe I can set this option at work. Though it's scary because I'd have to be certain.
Re: The Performance Impact of C++'s `final` Keyword
#313Earlier quoted context omitted.
No, I meant that we've written a compiler, based on Roslyn, whose runtime for compiling the code has improved by 20 % when switching to .NET 6. And indeed, on the C# -> IL side there's little that's being actually optimized. Besides collection literals there's also switch statements/expressions over strings, along with certain pattern matching constructs that get improved on that side.
Interesting! (I was way off the mark, not reading carefully, ha) Is it a public project?
Re: The Performance Impact of C++'s `final` Keyword
#314I don't do much C++, but I have definitely found that engineers will just assert that something is "faster" without any evidence to back that up. Quick example, I got in an argument with someone a few years ago that claimed in C# that a `switch` was better than an `if(x==1) elseif(x==2)...` because switch was "faster" and rejected my PR. I mentioned that that doesn't appear to be true, we went back and forth until I…
> `if(x==1) elseif(x==2)...` because switch was "faster" and rejected my PR Yeah, that's never been true. Old compilers would often compile a switch to __slower__ code because they'd tend to always go to a jump table implementation. A better reason to use the switch is because it's better style in C-like languages. Using an if statement for that sort of thing looks like Python; it makes the code harder to maintain.
(Also, Python has a switch-like construct now.)
Re: The Performance Impact of C++'s `final` Keyword
#315What final enables is devirtualization in certain cases. The main advantage of devirtualization is that it is necessary for inlining. Inlining has other requirements as well -- LTO pretty much covers it. The article doesn't have sufficient data to tell whether the testcase is built in such a way that any of these optimizations can happen or is beneficial.
> What final enables is devirtualization in certain cases. The main advantage of devirtualization is that it is necessary for inlining. I think that enabling inlining is just one of the indirect consequences of devirtualization, and perhaps one that is largely irrelevant for performance improvements. The whole point of devirtualization is eliminating the need to resort to pointer dereferencing when calling virtual me…
virtual inheritance. Regular old inheritance does not need or benefit from devirtualization. This is why the CRTP exists.
Re: The Performance Impact of C++'s `final` Keyword
#316Earlier quoted context omitted.
> What final enables is devirtualization in certain cases. The main advantage of devirtualization is that it is necessary for inlining. I think that enabling inlining is just one of the indirect consequences of devirtualization, and perhaps one that is largely irrelevant for performance improvements. The whole point of devirtualization is eliminating the need to resort to pointer dereferencing when calling virtual me…
> Devirtualization helps performance because you are able to benefit from inheritance and not have to pay a performance penalty for that. Without the final keyword, a performance oriented project would need to be architected to not use inheritance at all, or in the very least in code in the hot path, because that sneaks gratuitous pointer dereferences all over the place, which require running extra operations and has…
CRTP does not exist for that. CRTP was one of the many happy accidents in template metaprogramming that happened to be discovered when doing recursive templates.
Also, you've missed the whole point. CRTP is a way to rearchitect your code to avoid dereferencing pointers to virtual members in inheritance. The whole point is that with final you do not need to pull tricks: just tell the compiler that you don't want the class to be inherited, and the compiler picks up from there and does everything for you.
Re: The Performance Impact of C++'s `final` Keyword
#317Earlier quoted context omitted.
> That's the first problem I see with the article. C++ isn't a fast language, as it is. There are far too many issues with e.g. aliasing rules, lack of proper vectorization (for the runtime arch), etc. That's a bold statement due to the way it heavily contrasts with reality. C++ is ever present in high performance benchmarks as either the highest performing language or second only to C. It's weird seeing someone clai…
> That's a bold statement due to the way it heavily contrasts with reality. I'm ready to back this up. And no, I'm not confusing things - I work in HPC (realtime computer vision) and in reality the only thing we'd use C++ for is "glue", i.e. binding implementations of the actual algorithms implemented in other languages together. Implementations could be e.g. in CUDA, ISPC, neural-inference via TensorRT, etc.
But to add to all the nonsense,you claim otherwise.
Frankly, your comments lack any credibility, which is confirmed by your lame appeal to authority.
Re: The Performance Impact of C++'s `final` Keyword
#318Earlier quoted context omitted.
In general the compiler/linker cannot assume that derived classes won't arrive later through a shared object. You can tell it "I won't do that" though with additional flags, like Clang's -fwhole-program-vtables, and even then it's not that simple. There was an effort in Clang to better support whole program devirtualization, but I haven't been following what kind of progress has been made: https://groups.google.com/g…
This optimization option isn't on by default? That sounds like a lot of missed optimization. Most programs aren't going to be loading from shared libraries. Maybe I can set this option at work. Though it's scary because I'd have to be certain.
Re: The Performance Impact of C++'s `final` Keyword
#319Earlier quoted context omitted.
> Devirtualization helps performance because you are able to benefit from inheritance and not have to pay a performance penalty for that. Without the final keyword, a performance oriented project would need to be architected to not use inheritance at all, or in the very least in code in the hot path, because that sneaks gratuitous pointer dereferences all over the place, which require running extra operations and has…
> This is why the CRTP exists. CRTP does not exist for that. CRTP was one of the many happy accidents in template metaprogramming that happened to be discovered when doing recursive templates. Also, you've missed the whole point. CRTP is a way to rearchitect your code to avoid dereferencing pointers to virtual members in inheritance. The whole point is that with final you do not need to pull tricks: just tell the com…
Re: The Performance Impact of C++'s `final` Keyword
#320Earlier quoted context omitted.
If you already have LTO, can't the compiler determine this information for devirtualization purposes on its own?
This is one of the cases where JIT compiling can shine. You can use a bazillion interfaces to decouple application code, and the JIT will optimize the calls after it found out which implementation is used. This works as long as there is only one or two of them actually active at runtime.