[SAOC 2026] DMD CTFE Performance Update #2
Abul Hossain Khan
abulkhan19175 at gmail.com
Tue Oct 6 13:50:14 UTC 2026
Hi everyone,
Last time I went through the CTFE entrypoints and benchmarked
Dennis's linear memory prototype. After that we had a call and
decided to first measure how CTFE really behaves on real code. So
that's what I did.
#### Probing
The interface we want is "here is a function, it's complete, run
it, give me the result". What breaks that is semantic analysis
getting triggered in the middle of CTFE. To see how much that
happens I put a counter in `ctfeInterpret` and hooks in the
semantic functions, each hit saves a backtrace. Also counted
which `EXP` kinds go in and come out. Ran it on the test suite,
the Phobos build and every Phobos module with `-unittest`.
- Semantic does run inside CTFE, in about 1% of the calls. Only 5
different paths lead there, and really just one of them matters,
calling a function whose body isn't analysed yet, mostly
functions from imported modules.
- ~85% of `ctfeInterpret` calls return the input untouched, it's
just simple constant folding.
- Out of 124 `EXP` kinds, 49 go in, 80 get evaluated inside and
only 20 come out.
- The result is complete, the compiler doesn't have to analyse it
again.
The lists and a minimal test for each of the 5 paths are here -
https://gist.github.com/abulgit/43f640a032c95557de959f7120d4fd69
#### Doing the semantic upfront
I added a pre-pass that walks every function body the call can
reach and analyses it first.
| | Normal | with pre-pass |
|---|--:|--:|
| semantic inside CTFE, test suite | 10,008 | 11 |
| semantic inside CTFE, Phobos unittests | 17,711 | 88 |
| failing tests if semantic inside CTFE is an error | 732 | 13 |
So it works, the only thing left is virtual calls, where the
override that runs isn't known before. 11 tests fail with the
pre-pass but it's only a different line after an error.
But it also breaks valid code that isn't in the test suite. Like
a const that is read in a branch which isn't taken while that
const is computed, or a function from an imported module that
never runs but gives an error with `-de` or `-betterC`.
#### What's next
- Will try the other way, where the engine asks for semantic
through a callback, and compare the two.
- Also add a small code example for every expression kind in the
gist, and see if the list can be made smaller.
- Add a CTFE heavy workload to the perf bot.
If you have code where CTFE is slow or eats a lot of memory,
please share it here. A small self contained file is best, but a
dub package works too.
Thanks to Dennis for mentoring this. As always, feel free to
leave any feedback or suggestions!
More information about the Digitalmars-d
mailing list