Skip to content

Instantly share code, notes, and snippets.

@UplinkCoder
Last active November 22, 2020 12:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save UplinkCoder/d29dd143b352d28390426a3ffedf9521 to your computer and use it in GitHub Desktop.
Save UplinkCoder/d29dd143b352d28390426a3ffedf9521 to your computer and use it in GitHub Desktop.
# compiler commit hash: 0e837363832a5deb0447e10f9e615c0497e521f7
# which got compiled with the following commandline:
# make -f posix.mak HOST_DMD=~/d/ldc2-1.23.0-linux-x86_64/bin/ldmd2 DFLAGS+="-g -O3"
uplimk@uplimk-virtual-machine:~/d/dmd$ hyperfine -w 10 "generated/linux/release/64/dmd xx_tf.d -sktf -c" "generated/linux/release/64/dmd xx.d -c " "generated/linux/release/64/dmd xx_adam.d -c"
Benchmark #1: generated/linux/release/64/dmd xx_tf.d -sktf -c
Time (mean ± σ): 9.1 ms ± 0.4 ms [User: 5.8 ms, System: 3.2 ms]
Range (min … max): 8.5 ms … 10.7 ms 288 runs
0.02user 0.01system 0:00.04elapsed 92%CPU (0avgtext+0avgdata 11672maxresident)k
0inputs+8outputs (0major+1769minor)pagefaults 0swaps
tuple((uint), (dchar), (int), (ulong), (long))
0.02user 0.01system 0:00.04elapsed 97%CPU (0avgtext+0avgdata 11556maxresident)k
0inputs+0outputs (0major+1768minor)pagefaults 0swaps
tuple((uint), (dchar), (int), (ulong), (long))
0.02user 0.01system 0:00.03elapsed 94%CPU (0avgtext+0avgdata 11660maxresident)k
Benchmark #2: generated/linux/release/64/dmd xx.d -c
Time (mean ± σ): 17.3 ms ± 0.6 ms [User: 11.3 ms, System: 5.9 ms]
Range (min … max): 16.5 ms … 19.5 ms 166 runs
0.05user 0.01system 0:00.07elapsed 97%CPU (0avgtext+0avgdata 24960maxresident)k
0inputs+8outputs (0major+5120minor)pagefaults 0swaps
(int, uint, long, ulong, float, double, real, dchar)
0.03user 0.01system 0:00.05elapsed 88%CPU (0avgtext+0avgdata 24936maxresident)k
0inputs+0outputs (0major+5120minor)pagefaults 0swaps
(int, uint, long, ulong, float, double, real, dchar)
0.05user 0.00system 0:00.06elapsed 98%CPU (0avgtext+0avgdata 24940maxresident)k
0inputs+0outputs (0major+5119minor)pagefaults 0swaps
Benchmark #3: generated/linux/release/64/dmd xx_adam.d -c
Time (mean ± σ): 20.4 ms ± 0.7 ms [User: 15.2 ms, System: 5.0 ms]
Range (min … max): 19.5 ms … 22.7 ms 144 runs
0.05user 0.00system 0:00.06elapsed 95%CPU (0avgtext+0avgdata 19476maxresident)k
0inputs+8outputs (0major+3745minor)pagefaults 0swaps
(ushort, wchar, short, uint, dchar, int, ulong, long)
0.03user 0.02system 0:00.05elapsed 91%CPU (0avgtext+0avgdata 19564maxresident)k
0inputs+0outputs (0major+3749minor)pagefaults 0swaps
(ushort, wchar, short, uint, dchar, int, ulong, long)
0.04user 0.01system 0:00.06elapsed 92%CPU (0avgtext+0avgdata 19552maxresident)k
0inputs+0outputs (0major+3745minor)pagefaults 0swaps
Summary
'generated/linux/release/64/dmd xx_tf.d -sktf -c' ran
1.91 ± 0.11 times faster than 'generated/linux/release/64/dmd xx.d -c '
2.24 ± 0.13 times faster than 'generated/linux/release/64/dmd xx_adam.d -c'
template ApplyLeft(alias Template, args...)
{
alias ApplyLeft(right...) = SmartAlias!(Template!(args, right));
}
private template SmartAlias(T...)
{
static if (T.length == 1)
{
alias SmartAlias = Alias!T;
}
else
{
alias SmartAlias = T;
}
}
alias Alias(alias a) = a;
alias Alias(T) = T;
template Filter(alias pred, TList...)
{
static if (TList.length < filterExpandFactor)
{
mixin(FilterShortCode[TList.length]);
}
else
{
template MaybeNothing(Q...)
{
static if (pred!(Q[0]))
alias MaybeNothing = AliasSeq!(Q[0]);
else
alias MaybeNothing = Nothing;
}
alias Filter = staticMap!(MaybeNothing, TList);
}
}
private enum staticMapExpandFactor = 150;
private string generateCases()
{
string[staticMapExpandFactor] chunks;
chunks[0] = q{};
static foreach (enum i; 0 .. staticMapExpandFactor - 1)
chunks[i + 1] = chunks[i] ~ `F!(Args[` ~ i.stringof ~ `]),`;
string ret = `AliasSeq!(`;
foreach (chunk; chunks)
ret ~= `q{alias staticMap = AliasSeq!(` ~ chunk ~ `);},`;
return ret ~ `)`;
}
private alias staticMapBasicCases = AliasSeq!(mixin(generateCases()));
/**
Evaluates to $(D AliasSeq!(F!(T[0]), F!(T[1]), ..., F!(T[$ - 1]))).
*/
template staticMap(alias F, Args...)
{
static if (Args.length < staticMapExpandFactor)
mixin(staticMapBasicCases[Args.length]);
else
alias staticMap = AliasSeq!(staticMap!(F, Args[0 .. $ / 2]),
staticMap!(F, Args[$ / 2 .. $]));
}
alias AliasSeq(TList...) = TList;
private alias FilterShortCode = AliasSeq!(q{
alias Filter = Nothing;
}, q{
static if (pred!(TList[0]))
alias Filter = AliasSeq!(TList[0]);
else
alias Filter = Nothing;
}, q{
static if (pred!(TList[0]))
{
static if (pred!(TList[1]))
alias Filter = AliasSeq!(TList[0], TList[1]);
else
alias Filter = AliasSeq!(TList[0]);
}
else
{
static if (pred!(TList[1]))
alias Filter = AliasSeq!(TList[1]);
else
alias Filter = Nothing;
}
}, q{
static if (pred!(TList[0]))
{
static if (pred!(TList[1]))
{
static if (pred!(TList[2]))
alias Filter = AliasSeq!(TList[0], TList[1], TList[2]);
else
alias Filter = AliasSeq!(TList[0], TList[1]);
}
else
{
static if (pred!(TList[2]))
alias Filter = AliasSeq!(TList[0], TList[2]);
else
alias Filter = AliasSeq!(TList[0]);
}
}
else
{
static if (pred!(TList[1]))
{
static if (pred!(TList[2]))
alias Filter = AliasSeq!(TList[1], TList[2]);
else
alias Filter = AliasSeq!(TList[1]);
}
else
{
static if (pred!(TList[2]))
alias Filter = AliasSeq!(TList[2]);
else
alias Filter = Nothing;
}
}
}, q{
static if (pred!(TList[0]))
{
static if (pred!(TList[1]))
{
static if (pred!(TList[2]))
{
static if (pred!(TList[3]))
alias Filter = AliasSeq!(TList[0], TList[1], TList[2], TList[3]);
else
alias Filter = AliasSeq!(TList[0], TList[1], TList[2]);
}
else
{
static if (pred!(TList[3]))
alias Filter = AliasSeq!(TList[0], TList[1], TList[3]);
else
alias Filter = AliasSeq!(TList[0], TList[1]);
}
}
else
{
static if (pred!(TList[2]))
{
static if (pred!(TList[3]))
alias Filter = AliasSeq!(TList[0], TList[2], TList[3]);
else
alias Filter = AliasSeq!(TList[0], TList[2]);
}
else
{
static if (pred!(TList[3]))
alias Filter = AliasSeq!(TList[0], TList[3]);
else
alias Filter = AliasSeq!(TList[0]);
}
}
}
else
{
static if (pred!(TList[1]))
{
static if (pred!(TList[2]))
{
static if (pred!(TList[3]))
alias Filter = AliasSeq!(TList[1], TList[2], TList[3]);
else
alias Filter = AliasSeq!(TList[1], TList[2]);
}
else
{
static if (pred!(TList[3]))
alias Filter = AliasSeq!(TList[1], TList[3]);
else
alias Filter = AliasSeq!(TList[1]);
}
}
else
{
static if (pred!(TList[2]))
{
static if (pred!(TList[3]))
alias Filter = AliasSeq!(TList[2], TList[3]);
else
alias Filter = AliasSeq!(TList[2]);
}
else
{
static if (pred!(TList[3]))
alias Filter = AliasSeq!(TList[3]);
else
alias Filter = Nothing;
}
}
}
});
private enum filterExpandFactor = FilterShortCode.length;
package alias Nothing = AliasSeq!(); // yes, this really does speed up compilation!
alias Numerics = AliasSeq!(byte, ubyte, short, ushort, int, uint, long,
ulong, float, double, real, char, wchar, dchar);
enum convertsTo(T, U) = is(T : U);
alias ImplicitConversionTargets(T) = Filter!(ApplyLeft!(convertsTo, T), Numerics);
pragma(msg, ImplicitConversionTargets!uint);
enum basic_types = ["bool", "ubyte", "char", "byte", "ushort", "wchar", "short", "uint", "dchar", "int", "ulong", "long"];
// to not import stdlib
alias AliasSeq(T...) = T;
string join(string[] s, string j) {
string a;
foreach(i; s)
a ~= i ~ j;
return a;
}
template basicTypeConvTargets(T) {
// again, I copy/pasted your code with very slight modifications
string[] helper() {
string[] targets;
targets.length = basic_types.length;
size_t n = 0;
static foreach(t;basic_types)
{
if (is(T : mixin(t)))
{
targets[n++] = t;
}
}
return targets[0 .. n];
}
mixin("alias basicTypeConvTargets = AliasSeq!(" ~ helper().join(",") ~ ");");
}
pragma(msg, basicTypeConvTargets!ushort);
alias type = __type__;
// needed to avoid deeper changes ... in the future it may be unnecessary.
auto makeAliasArray(type[] types ...)
{
return types;
}
enum basic_types = makeAliasArray(bool, ubyte, char, byte, ushort, wchar, short, uint, dchar, int, ulong, long);
type[] convTargets(type T)
{
if (isBasicType(T))
return basicTypeConvTargets(T);
return null;
}
bool isBasicType(type T)
{
foreach(t;basic_types)
{
if (is(T == t))
return true;
}
return false;
}
type[] basicTypeConvTargets(type T)
{
type[] targets;
targets.length = basic_types.length;
assert(isBasicType(T), "You may not call this function when you don't have a basic type ... (given: " ~ T.stringof ~ ")");
size_t n = 0;
foreach(t;basic_types)
{
if (is(T : t))
{
targets[n++] = t;
}
}
return targets[0 .. n];
}
pragma(msg, basicTypeConvTargets(int).tupleof);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment