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

Reply via email to