digitalmars.D - Inlining Virtual Functions
dsimcha <dsimcha yahoo.com> writes:
According to the spec: "Virtual functions are functions that are called indirectly through a function pointer table, called a vtbl, rather than directly. All non-static non-private non-template member functions are virtual. This may sound inefficient, but since the D compiler knows all of the class hierarchy when generating code, all functions that are not overridden can be optimized to be non-virtual. In fact, since C++ programmers tend to "when in doubt, make it virtual", the D way of "make it virtual unless we can prove it can be made non-virtual" results, on average, in many more direct function calls. It also results in fewer bugs caused by not declaring a function virtual that gets overridden." Under what circumstances is this actually true? As far as I can tell, there is no way DMD could know about the whole class hierarchy when generating code, given that in practice modules are compiled separately. Not arguing that methods should be made non-virtual by default, since the current behavior is consistent with the "make it safe by default, efficient but unsafe if the programmer asks" mentality, and one can always convert a function to non-virtual by making it final. However, I'm just curious under what circumstances converting virtual functions into direct calls is actually possible.
Feb 27 2009
bearophile <bearophileHUGS lycos.com> writes:
dsimcha:Under what circumstances is this actually true?
At the moment I think that spec is pure theory for DMD, even if it's worded to almost sound as the compiler already works like that :-)As far as I can tell, there is no way DMD could know about the whole class hierarchy when generating code, given that in practice modules are compiled separately.<
I think with LDC it will be possible to perform global optimizations among different modules, allowing such optimization too, in some situations (LDC developers may confirm of deny this). For Java (and this may be true for C# of dotnet too) a virtual machine like HotSpot is able to analyze the call loci and compile and/or inline code dynamically. Sometimes it's able to turn a virtual dispatch into a direct call, sometimes such virtual dispatch is replaced with a branch with two possible direct calls, and sometimes it puts a test that allows a direct call in most cases or a virtual dispatch as fallback for the less common case. There are even more complex cases, but you often don't gain much more. Removing virtual calls speeds up code a little by itself, but then later it allows the compiler to inline methods, and this may speed up code significantly in inner loops. A possibility for D is runtime-driven optimization: you compiler and run the code, the compiler collects statistics on the virtual call sites (among many other kinds of statistics) and then you can re-compile your code letting the compiler use such run-time information to inline things, etc. Of course your test run must be significant of the final normal usage of your code, otherwise you optimize against the wrong things (while HotSpot runs concurrently of your code, so it surely collects real-world data). The GCC (and Intel) compiler is already able to perform such collection of run-time statistics, with -fprofile-generate and -fprofile-use, but I don't know if it uses such information to inline ex-virtual calls too. This too is related: http://www.digitalmars.com/ctg/trace.html Bye, bearophile
Feb 27 2009