Bug 16330 – Expansion of code (static foreach, templates) is too slow

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2016-07-28T09:01:37Z
Last change time
2024-12-13T18:49:16Z
Assigned to
No Owner
Creator
Walter Bright
Moved to GitHub: dmd#17768 →

Comments

Comment #0 by bugzilla — 2016-07-28T09:01:37Z
Ethan Watson writes: Expansion of code (static foreach, templates) is slow to the point where string mixins are a legitimate compile-time optimisation Take an example of whittling down a tuple/variable argument list. Doing it recursively would look something like this: template SomeEliminator( Symbols... ) { static if( Symbols.length >= 1 ) { static if( SomeCondition!( Symbol[ 0 ] ) ) { alias SomeEliminator = TypeTuple!( Symbol[ 0 ], Symbols[ 1 .. $ ] ); } else { alias SomeEliminator = TypeTuple!( Symbols[ 1 .. $ ] ); } } else { alias SomeEliminator = TypeTuple!( ); } } Okay, that works, but the template expansion is a killer on compile-time performance. It's legitimately far quicker on the compiler to do this: template SomeEliminator( Symbols... ) { string SymbolSelector() { string[] strOutputs; foreach( iIndex, Symbol; Symbols ) { static if( SomeCondition!( Symbol ) ) { strOutputs ~= "Symbols[ " ~ iIndex.stringof ~ " ]"; } } return strOutputs.joinWith( ", " ); } mixin( "alias SomeEliminator = TypeTuple!( " ~ SymbolSelector() ~ " );" ); } With just a small codebase that I'm working on here, it chops seconds off the compile time. Of course, maybe there's something I'm missing here about variable parameter parsing and doing it without a mixin is quite possible and just as quick as the mixin, but that would make it the third method I know of to achieve the same effect. The idiomatic way of doing this without mixins should at least be defined, and optimised at the compiler level so that people don't get punished for writing natural D code. Then there was this one that I came across: outofswitch: switch( symbolName ) { foreach( Variable; VariablesOf!( SearchType ) ) { case Variable.Name: doSomething!( Variable.Type )(); break outofswitch; } default: writeln( symbolName, " was not found!" ); break; } This caused compile time to blow way out. How far out? By rewriting it like this, I cut compile times in half (at that point, from 10 seconds to 5): switch( symbolName ) { mixin( generateSwitchFor!( SearchType )() ); default: writeln( symbolName, " was not found!" ); break; } Now, I love mixins, both template form and string form. The binding system uses them extensively. But mixins like this are effectively a hack. Anytime I have to break out a mixin because my compile time doubled from a seemingly simple piece of code is not good.
Comment #1 by robert.schadek — 2024-12-13T18:49:16Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17768 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB