The Performance Impact of C++'s `final` Keyword
181–190 of 385 posts
Re: The Performance Impact of C++'s `final` Keyword
#182What should be evaluated is removing indirection and tightly packing your data. I'm sure you'll gain a better performance improvement. virtual calls and shared_ptr are littered in the codebase. In this way: you can avoid the need for the `final` keyword and do the optimization the keyword enables (de-virtualize calls). >Yes, it is very hacky and I am disgusted by this myself. I would never do this in an actual produc…
In modern C++, macros are a viewed as a code smell because they are strictly worse than alternatives in almost all situations. It is a cultural norm; it is a bit like using "unsafe" in Rust if not strictly required for some trivial case. The C++ language has made a concerted effort to eliminate virtually all use cases for macros since C++11 and replace them with type-safe first-class features in the language. It is a…
Re: The Performance Impact of C++'s `final` Keyword
#183Re: The Performance Impact of C++'s `final` Keyword
#184What 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.
See this is why I find this odd. Is there a theory as to how devirtualisation could hurt performance?
Guarded devirtualization is also cheaper than virtual calls, even when it has to do
if (instance is SpecificType st) { st.Call() }
else { instance.Call() }
or even chain multiple checks at once (with either regular ifs or emitting a jump table)This technique is heavily used in various forms by .NET, JVM and JavaScript JIT implementations (other platforms also do that, but these are the major ones)
The first two devirtualize virtual and interface calls (important in Java because all calls default to virtual, important in C# because people like to abuse interfaces and occasionally inheritance, C# delegates are also devirtualized/inlined now). The JS JIT (like V8) performs "inline caching" which is similar where for known object shapes property access is shape type identifier comparison and direct property read instead of keyed lookup which is way more expensive.
Re: The Performance Impact of C++'s `final` Keyword
#185Re: The Performance Impact of C++'s `final` Keyword
#186Re: The Performance Impact of C++'s `final` Keyword
#187Re: The Performance Impact of C++'s `final` Keyword
#188Why would I expect no performance difference? I haven't looked at the code, but I would expect that for each pixel, it iterates through an array/vector/list etc. of objects that implement some common interface, and calls one or more methods (probably something called intersectRay() or similar) on that interface. By design, that interface cannot be made final, and that's what counts. Whether the concrete derived classes are final or not makes no difference.
In order to make this a good test of "final", the pointer type of that container should be constrained to a concrete object type, like Sphere. Of course, this means the scene is limited to spheres.
The only case where final can make a difference, by devirtualising a call that couldn't otherwise be devirtualised, is when you hold a pointer to that type, and the object it points at was allocated "uncertainly", e.g., by the caller. (If the object was allocated in the same basic block where the method call later occurs, the compiler already knows its runtime type and will devirtualise the call anyway, even without "final".)