Update on the D-to-Jai guy: We have real problems with the language

FeepingCreature feepingcreature at gmail.com
Sun Nov 27 09:29:29 UTC 2022


I've had an extended Discord call taking a look at the codebase. 
Now, these are only my own thoughts, but I'd share them anyway:

- This is a fairly pedestrian codebase. No CTFE craziness, 
restrained "normal" use of templates. It's exactly the sort of 
code that D is supposed to be fast at.
- To be fair, his computer isn't the fastest. But it's an 8core 
AMD, so DMD's lack of internal parallelization hurts it here. 
This will only get worse in the future.
- And sure, there's a bunch of somewhat quadratic templates that 
explode a bit. But!

But!

1. It's all "pedestrian" use. Containers with lots of members 
instantiated with lots of types.
2. The compiler doesn't surface what is fast and what is slow and 
doesn't give you a way to notice it, no -vtemplates isn't enough, 
we need a way to tell the *time taken* not just the number of 
instantiations.
3. But also if we're talking about number of instantiations, 
`hasUDA` and `getUDA` lead the pack. I think the way these work 
is just bad - I've rewritten all my own `hasUDA`/`getUDA` code to 
be of the form `udaIndex!(U, __traits(getAttributes, T))` - 
instantiating a unique copy for every combination of field and 
UDA is borderline quadratic - but that didn't help much even 
though `-vtemplates` hinted that it should. `-vtemplates` needs 
compiler time attributed to template recursively.
4. LLVM is painful. Unavoidable, but painful. Probably twice the 
compile time of the ldc2 run was in the LLVM backend.
5. There was no smoking gun. It's not like "ah yeah, this thing, 
just don't do it." It's a lot of code that instantiates a lot of 
genuine workhorse templates (99% "function with type" or "struct 
with type"), and it was okay for a long time and then it wasn't.

I really think the primary issue here is just that D gives you a 
hundred tools to dig yourself in a hole, and has basically no 
tools to dig yourself out of it, and if you do so you have to go 
"against the grain" of how the language wants to be used. And 
like, as an experienced dev I know the tricks of how to optimize 
templates, and I've sunk probably a hundred hours into this for 
my two libs at work alone, but this is *folk knowledge*, it's not 
part of the stdlib, or the spec, or documented anywhere at all. 
Like `if (__ctfe) return;`. Like `udaIndex!(__traits)`. Like 
`is(T : U*, U)` instead of `isPointer`. Like making struct 
methods templates so they're only compiled when needed. Like 
moving recursive types out of templates to reduce the compilation 
time. Like keeping your unique instantiations as low as possible 
by querying information with traits at the site of instantiation. 
Like `-v` to see where time is spent. Like ... and so on. This 
goes for every part of the language, not just templates.

DMD is fast. DMD is even fast for what it does. But DMD is not as 
fast as it implicitly promises when templates are advertised, and 
DMD does not expose enough good ways to make your code fast again 
when you've fallen in a hole.



More information about the Digitalmars-d mailing list