On exceptions in D

inout inout at gmail.com
Sun Feb 9 17:49:40 PST 2014


On Monday, 10 February 2014 at 01:16:27 UTC, Jonathan M Davis
wrote:
> On Sunday, February 09, 2014 21:57:13 Dmitry Olshansky wrote:
>> Split out of "List of Phobos functions that allocate memory?".
>> 
>> To reiterate, here is some critique, compiled:
>> 
>> 1. Exceptions are class instances, hence (by default) are 
>> allocated on
>> GC heap. This is wrong default, GC is no place for temporaries.
>
> The more I think about it, the less I'm convinced that this is 
> a big deal.
> Sure, it would be nice if they were malloc-ed and 
> reference-counted so that
> they'd go away immediately after they were used and didn't risk 
> triggering a
> collection, but for exceptions to work right, they need 
> inheritance, so they
> have to be classes, and since exceptions are generally rare, 
> having the extra
> overhead of the memory allocation usually isn't a big deal, and 
> if it triggers
> a collection or sticks around for a little while after it's 
> used (because no
> collection gets run), most code won't care.
>
> The code that really cares is code that's having to throw 
> exceptions more
> frequently and/or in situations where those exceptions really 
> need to be fast.
> Personally, I've only run into that in unit tests, and I don't 
> think that the
> GC has much do with that slowness (and Adam Ruppe's current 
> work on that seems
> to support that it's not the GC that's an issue). So, if the 
> stack traces (or
> whatever it is that's making them slow) can be fixed to be 
> faster, then as far
> as unit tests go, I would consider the matter taken care of and 
> the fact that
> the GC is used for exceptions to be a non-issue.
>
> The place where this becomes an issue then is code that needs 
> exceptions to be
> really fast (e.g. it sounds like vibe.d falls in that camp). 
> And in that case,
> it doesn't really matter whether the exceptions are allocated 
> on the GC heap
> or malloc's heap. If memory allocation is slowing them down, 
> then they need to
> get rid of the memory allocation entirely, in which case, doing 
> something like
> having a pool of pre-allocated exception objects to reuse would 
> make a lot
> more sense. And in that case, it would probably be better if 
> they weren't on
> the GC heap, but the exception-throwing code wouldn't really 
> care either way.
> That would be up to the pool. The same goes if only a single, 
> static exception
> were used. It might be marginally better if it weren't on the 
> GC heap, because
> it would avoid being scanned, but in those cases where you want 
> speed, you
> _want_ long lifetimes for the exceptions, not short lifetimes 
> like you're
> suggesting, because you want to reuse the exceptions in order 
> to avoid needing
> to allocate new ones. The only way that short lifetimes would 
> work is if we
> weren't dealing with classes and the exceptions were on the 
> stack, but that
> negates our ability to have an exception hierarchy - which is 
> critical to how
> exceptions work.
>
> And if some code is getting exceptions frequently enough that 
> the memory
> allocation is the bottleneck, then maybe exceptions aren't the 
> best choice
> either. I agree that exceptions need to be much, much faster 
> than they are,
> but they're still intended for the error case, which should be 
> relatively
> infrequent.
>
>> 2. Stack trace is constructed on throw. User pays no matter if 
>> the trace
>> is needed or not. This is in the works, thankfully.
>
> Yes, which should be a significant improvement and likely a 
> much larger gain
> than any memory allocation issues.
>
>> 3. Turns out message is expected to be a string, formatted 
>> apriori:
>> https://github.com/D-Programming-Language/druntime/blob/master/src/object_.d
>> #L1306 Formatting a string in such setting inevitably 
>> allocates and it
>> happens at the throw site, even if nobody is using that 
>> message down the
>> line. At least one can override toString...
>
> Ideally, creating the string that toString returns would be put 
> off until
> toString is called (particularly since that includes the stack 
> trace), but I
> would hope that creating the message string to pass to the 
> exception's
> constructor would be cheap enough (particularly in light of the 
> fact that the
> exception is heap-allocated anyway) that it wouldn't be a big 
> deal. So, if we
> can find a way to make this more efficient without getting 
> messy, that's
> great, but I wouldn't expect that to be a bottleneck just so 
> long as the
> actual string that the message gets put into for toString to 
> return (which
> then includes the file and line and stacktrace and whatnot) 
> isn't created
> until toString is called.
>
> - Jonathan M Davis

All that wouldn't be a problem if D had ARC for everything,
including Exception`s.


More information about the Digitalmars-d mailing list