[Issue 16330] New: Expansion of code (static foreach, templates) is too slow
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Thu Jul 28 02:01:37 PDT 2016
https://issues.dlang.org/show_bug.cgi?id=16330
Issue ID: 16330
Summary: Expansion of code (static foreach, templates) is too
slow
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Severity: normal
Priority: P1
Component: dmd
Assignee: nobody at puremagic.com
Reporter: bugzilla at digitalmars.com
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.
--
More information about the Digitalmars-d-bugs
mailing list