Thoughts about D

H. S. Teoh hsteoh at quickfur.ath.cx
Fri Dec 1 01:17:58 UTC 2017


On Thu, Nov 30, 2017 at 11:12:58AM -0700, Jonathan M Davis via Digitalmars-d wrote:
> On Thursday, November 30, 2017 16:48:10 Adam D. Ruppe via Digitalmars-d 
> wrote:
> > On Thursday, 30 November 2017 at 16:12:04 UTC, H. S. Teoh wrote:
> > > Which brings us to the implementation of assert() itself. What
> > > about it makes it so big? I suspect most of the bloat comes from
> > > throwing AssertError, which pulls in the stack-unwinding code,
> > > which, if my memory is still up to date, suffers from performance
> > > issues where it tries to construct the stacktrace regardless of
> > > whether or not the catch block actually wants the stacktrace.
> >
> > That's false, I changed that many years ago myself, unless the DWARF
> > change involved that too, but I don't think so.
> >
> > What happens is the exception constructor walks the stack and copies
> > the addresses to a local, static buffer. This is very fast - just
> > walking a linked list and copying some void* into a void*[64] or
> > whatever - and little code.
> >
> > The expensive part of formatting it to a string, actually looking up
> > the debug info, parsing out the addresses, etc., is done lazily when
> > it is printed, which occurs only on demand or right before the
> > program terminates.
> 
> Yeah, that change was a _huge_ speedup. It had a significant impact on
> std.datetime's unit tests.
[...]

Ah yes, now I vaguely remember that somebody, I guess it was you Adam,
fixed that stacktrace thing.

Still, I think Walter's complaint wasn't the *performance* of assert()
per se, since the cost of evaluating the expression should be pretty
small, and the only real bottleneck is the stack unwinding, and I doubt
anybody actually cares about the *performance* of that. But the
complaint was about the code bloat of linking druntime into the
executable.  Before Adam's fix, assert() would create the entire the
stacktrace upon constructing the AssertError, which means it has to pull
in a whole bunch of code for decoding stack addresses and
cross-referencing them with symbols, etc., but all that code would be
useless if the user didn't care about the stacktrace to begin with.

With Adam's fix, there's now the possibility of templatizing the
stacktrace code so that the code won't even be compiled into the
executable until you actually use it.

I just took a quick glance at druntime, and it seems that the stacktrace
symbol lookup code currently is referenced by module static ctor, so it
will be included by default whether or not you use it.  I haven't looked
further but perhaps it's possible to refactor some of the code around
this to make it lazy / lazier, so that the code isn't actually
instantiated until your program actually calls it.

In general, I think druntime / Phobos should adopt the policy of zero
cost until first use / first reference, where possible.  Things like the
GC are probably too tightly integrated for this to be possible, but I
think there's still plenty of room for improvement with other parts of
druntime and Phobos.


T

-- 
Three out of two people have difficulties with fractions. -- Dirk Eddelbuettel


More information about the Digitalmars-d mailing list