Contracts or Exceptions?

Ali Çehreli acehreli at yahoo.com
Wed Mar 30 14:05:01 PDT 2011


On 03/30/2011 12:40 PM, Jonathan M Davis wrote:
> On 2011-03-30 05:09, spir wrote:
>> On 03/30/2011 05:32 AM, Ali Çehreli wrote:
>>> On 03/29/2011 03:40 PM, Kai Meyer wrote:
>>>>   I was given two words of advice on exceptions:
>>>>   "Use exceptions for the exceptional"
>>>>   "Use exceptions only for the exceptional"
>>>
>>> Those advices are given by wise people: they are wise only because they
>>> leave the definition as vague as "exceptional." :)
>>>
>>> And what do we do for the "not so exceptional"? Do we return error codes?
>>> So the function implementation will be complicated and the caller code
>>> will be complicated.
>>>
>>> Exceptions are a great tool to eliminate the need for error codes.
>>>
>>> Here is what I follow:
>>>
>>> - Functions have specific tasks to do; if those tasks cannot be
>>> accomplished, the function must throw.
>>>
>>> In some cases the function can continue, but that behavior must be
>>> documented. For example, if an HTML library function is responsible for
>>> making HTML headers, of which only the levels in the range of 1-6 are
>>> valid, that function may throw when the level is outside of the valid
>>> range, for in that case it cannot "make an HTML header"; or it can
>>> document that if the level is outside of the range, 1 or 6 will be used.
>>>
>>> - Catch exceptions only when there is a sensible thing to do at that
>>> level: log an error, skip that operation, go back to the user with an
>>> error code, take corrective action, etc.
>>>
>>> Disclaimer: That is what I follow in C++ code. I don't have experience
>>> with exception safety in D. I don't know issues that may be specific to
>>> D.
>>
>> These are sensible and well expressed guidelines, thank you.
>> In other languages, I happened to use exceptions as a // channel for
>> side-information (eg 'nomatch' for a matching func), but in D I realised
>> how 'exceptionnally' (!) costly throwing&  catching exceptions is, so that
>> I do not do it anymore. No idea though whether this exceptional cost is
>> perticular to D.
>
> I'd have to measure it in C++, Java, and C#, but I'm pretty sure that D's is
> at least a lot slower than Java. Java uses exceptions all over the place, and
> it works quite well overall IMHO, but I never got the impression that there
> was any kind of major overhead for exceptions (though obviously there's going
> to be at least _some_ performance hit for derailing the thread of execution
> like that). In D however, it seems to be significant. As I've been reworking
> std.datetime's unit tests, I've found that I've had to be very careful about
> how often I use assertThrown, or there is a _major_ increase in how long the
> unit tests take to execute. While changing some tests, I had some loops which
> included assertThrown. It turns out that with assertThrown, they'd be 10+
> seconds long, whereas without, they'd be a matter of milliseconds. So, the
> performance of exceptions in D is quite poor and while it probably doesn't
> matter all that much for normal code execution, it's definitely annoying for
> heavy unit testing which is validating that functions throw when they're
> supposed to throw.
>
> As a test, on my machine, this program
>
> ===
> import std.datetime;
> import std.exception;
> import std.stdio;
>
> void main()
> {
>      auto date = Date(2011, 5, 7);
>      {
>          auto curr = Clock.currTime();
>          assertNotThown!DateTimeException(date.day = 29);
>          writeln(curr - Clock.currTime());
>      }
>
>      {
>          auto curr = Clock.currTime();
>          assertThrown!DateTimeException(date.day = 32);
>          writeln(curr - Clock.currTime());
>      }
> }
> ===
>
> prints out this
>
> -1 μs and -4 hnsecs
> -637 μs and -7 hnsecs

That's too much. :) I get consistent results with -O on a 64-bit Ubuntu:

-1 μs and -9 hnsecs
-832 μs and -9 hnsecs

But with the addition of the -m64 flag, it's more than 4 times faster:

-1 μs
-175 μs and -4 hnsecs

Still not good. :-/

Ali

>
> Naturally, the executation time does vary some, but it's consistently over 400
> times (and generally more like 450 times) more expensive to have the exception
> be thrown and caught than it is to have it not be thrown. That's _really_
> expensive. I'd be stunned if Java's or C#'s were that bad, but I'd have to go
> and test it. C++'s might be, but given how much Java and C# use exceptions, it
> would ludicrous if either of them had that kind of overhead for exceptions.
>
> - Jonathan M Davis



More information about the Digitalmars-d-learn mailing list