Bug 6528 – Private module functions optimizations

Status
RESOLVED
Resolution
WONTFIX
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2011-08-18T14:20:15Z
Last change time
2022-07-12T12:51:29Z
Keywords
diagnostic, performance
Assigned to
No Owner
Creator
bearophile_hugs

Comments

Comment #0 by bearophile_hugs — 2011-08-18T14:20:15Z
The "private" attribute for module-level functions offers some optimization opportunities that I think DMD/D-front-end is not using. Example 1, space optimization: I like the fact that many functions are able to run both at run-time and compile-time, like some string functions. But I think that often user-define compile-time functions are never called at run-time. If such functions are also private, then they can't be called from other modules: module Foo; private int sqr(in int x) pure { return x; } enum y = sqr(10); void main() {} In this case I think the compiler is free to not put the implementation of sqr() into the final binary, saving binary space. --------------------- Example 2, performance optimization: if a global function is private, the compiler is free to change and optimize its signature. An example function: private void foo(int[] a1, int[] a2) {} void main() { int n = 100; // run-time value auto a3 = new int[n]; auto a4 = new int[n]; foo(a3, a4); } I think the compiler is free to optimize it into something like this (this is faster because now the function receives only 3 words instead of 4. If foo() gets called really many times this is able to make a certain performance difference): private void foo(int* a1, int* a2, size_t a1a2len) {} void main() { int n = 100; auto a3 = new int[n]; auto a4 = new int[n]; foo(a3.ptr, a4.ptr, n); }
Comment #1 by bearophile_hugs — 2011-08-20T01:14:33Z
Another optimization example: private void foo(int[] a) {} void main() { int[100] array; foo(array); } Converted to: private void foo(ref int[100] a) {} void main() { int[100] array; foo(array); } ------------------ The optimization is possible if foo has more than one call from the module, if the body of foo is short: private void foo(int[] a) { // this is a short function } void main() { int[100] array1; foo(array1); int[200] array2; foo(array2); } Converted to: private void foo(size_t N)(ref int[N] a) { // this is a short function } void main() { int[100] array1; foo(array1); int[200] array2; foo(array2); }
Comment #2 by hoganmeier — 2012-01-05T14:33:18Z
Also there should be a warning if you define a private function and not use it (including CTFE). Just like in C.
Comment #3 by yebblies — 2013-01-16T18:36:39Z
The first case here is already done by the linker.
Comment #4 by johannespfau — 2017-03-10T06:51:35Z
Reposting from the newsgroup: -------------------------------------------------------- // a.d private void fooPrivate() {} /*template*/ void fooPublic(string func = "fooPrivate")() { mixin(func ~ "();"); } -------------------------------------------------------- When compiling a.d we haven't analyzed the fooPublic template and the example shows why we can't know at all which private functions could be called from a template. As the template is instantiated into another object file (e.g. module b.d) we can't know in a.d that fooPrivate is actually required. So does that mean removing private functions in D is completely impossible as we can't know if a function is unused? People sometimes refer to the linker as a solution but if a.d is in a shared library this won't work either. This seems to be a problem especially for CTFE only functions, as it means for example that any such function in phobos (e.g. used for string creation for mixins) bloats the phobos library. It's interesting to think about template instances here as well: If a template instance is completely inlined in a module, do we have to keep the function in the object file? AFAICS no, as the template should be re-instantiated if used in a different module, but I don't know the template <=> object file rules in detail. Right now this means we could get lots of template instances in the phobos shared library for template instances only used in CTFE: -------------------------------------------------------- import std.conv; private string fooPrivate(int a) { return `int b = ` ~ to!string(a) ~";"; } mixin(fooPrivate(42)); -------------------------------------------------------- https://godbolt.org/g/VW8yLr Any idea to measure the impact of this on the binary shared libphobos file? We probably can get some estimate by counting all template instances that are only referenced by private functions which are themselves never referenced... I think the same problem was mentioned in the DLL-support context as this implies we also have to export private functions from modules for templates to work. Was there some kind of solution / discussion? I think I remember something about marking `private` functions as `export private` instead?
Comment #5 by ibuclaw — 2022-07-12T12:51:29Z
This is best handled at link or LTO time, as because of templates (called from outside the module compilation), we have no idea whether a private function really is used or not.