Bye bye, fast compilation times

H. S. Teoh hsteoh at quickfur.ath.cx
Wed Feb 7 01:20:04 UTC 2018


On Mon, Feb 05, 2018 at 01:27:57PM -0800, H. S. Teoh via Digitalmars-d wrote:
> One of my D projects for the past while has been taking unusually long
> times to compile.  This morning, I finally decided to sit down and
> figure out exactly why.
[...]

I don't want this thread to turn into ragging on std.regex, so here's
the next instalment of this saga.

After taking std.regex out of the equation, I found that there was still
something else that was bottlenecking my builds.  So I went for another
hunt, and discovered another guilty party: std.format.

----
import std.format;
void main() { format("a"); }
----

Here I found something interesting: compiling with -unittest takes over
0.8s. But compiling *without* -unittest takes only 0.4s.

The compilation times of std.format itself aside (it's pretty
heavyweight because of heavy template usage, and the recent compile-time
format string checking, while pretty cool functionally, also comes at
the price of heavier CTFE, i.e., slower compilation -- I'd like to leave
digging into std.format for later), it's a little disturbing that
compiling with -unittest *doubled* the compilation time.

This reinforces a concern I've been having recently, that is, library
unittests that get instantiated when user code is compiled with
-unittest.  I'll be the first to say that having built-in unittests in D
has revolutionized the way I write code -- it has dramatically increased
the average quality of my code. But its current simplicity comes at a
cost: if you're using external libraries (i.e., outside the immediate
codebase you're working with, so that includes Phobos), compiling with
-unittest automatically inherits all unittests from all libraries that
you import, even if said unittests have nothing to do with your own
code.

Put another way: why should you be concerned with Phobos unittests when
you're building your own code?  Phobos unittesting should have been (and
is) already done by the autotester and CIs on github; there's no reason
these tests have to be run over and over again in user code.

So I'd like to propose that we do something similar to what we did with
template instantiations a couple of years ago: make it so that unittests
are only instantiated if the module they occur in is being compiled,
otherwise ignore them (even in the face of -unittest).  This way, adding
unittests to Phobos won't cause unintentional slowdowns / unittest bloat
across *all* D projects that import the affected Phobos modules. (Seen
from this angle, it's a pretty hefty cost.)

Of course, this statement has to be qualified a bit: it's probably still
a good idea to instantiate unittests inside templates -- since
ostensibly they could be sanity-checking specific instantiations of
templates. Though I'd argue that 90% of the time, their location inside
a template is a mistake; they really should be outside templates and
only instantiated once, because generally they test specific
instantiations of the template rather than implement generic tests that
apply across all template instantiations.


T

-- 
Never step over a puddle, always step around it. Chances are that
whatever made it is still dripping.


More information about the Digitalmars-d mailing list