Performance of exception handling

Denis Koroskin 2korden at gmail.com
Tue Apr 26 11:56:39 PDT 2011


On Tue, 26 Apr 2011 22:26:00 +0400, Sean Kelly <sean at invisibleduck.org>  
wrote:

> On Apr 26, 2011, at 9:29 AM, Denis Koroskin wrote:
>
>> On Tue, 26 Apr 2011 20:14:05 +0400, Sean Kelly <sean at invisibleduck.org>  
>> wrote:
>>
>>> Right now, traces are generated on throw. It should be possible to  
>>> generate them on catch instead. The performance would be the same  
>>> either way however. It would be nice to generate them lazily but I  
>>> don't think that's possible.
>>>
>>> Sent from my iPhone
>>>
>>
>> Interesting enough, it is already done lazily (in toString(), which I  
>> believe should also cache result when it's called first time), but it  
>> can be improved a bit.
>
> The readable version is generated in toString, but the actual trace  
> occurs on throw.  This pretty much requires a memory allocation to store  
> the trace info, which is one cause for the performance hit.
>
> Originally, I didn't have the tracing enabled by default, but no one  
> seemed to like that.  I could try enabling it only for non-release  
> builds if that would be preferable.

You might have misunderstood me, or I might be wrong, but I believe you  
only need to store backtrace at the point where exception occurs, and  
resolve the symbols later (e.g. at toString()). Both are currently done in  
the DefaultTraceInfo ctor (see the code that you snipped).

Collecting the backtrace is very fast, and doesn't allocate on its own:

static enum MAXFRAMES = 128;
void*[MAXFRAMES]  callstack;

numframes = backtrace( callstack, MAXFRAMES );

It's the "backtrace_symbols" that does all the hard work, I believe, and  
as such moving it out of the DefaultTraceInfo ctor should be enough.

On the other had, DefaultTraceInfo could be made a struct and be moved to  
the Exception class to minimize allocations if you feel that exceptions  
should allocate as little as possible (if any at all, because they may end  
up throwing OutOfMemory exception).

Side question: we don't create OutOfMemory instances, throwing predefined  
ones instead, right? I don't think that work with exception chaining, does  
it? I mean, what if we e.g. catch an OOM, try to add a log entry, try to  
allocate and end up with OOM again. An exception chaining implemented with  
an intrusive linked list (i.e. implemented with an embedded Throwable  
next;) will not work for this case. Does druntime handle this case  
correctly?


More information about the Digitalmars-d mailing list