Contracts or Exceptions?

Jonathan M Davis jmdavisProg at gmx.com
Wed Mar 30 14:47:28 PDT 2011


On 2011-03-30 14:05, Ali Çehreli wrote:
> 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. :-/

LOL. And I just realized that I did those subtractions backwards. They're 
negative where they should be positive. Oh well. The numbers are still clear, 
and I was in a hurry when I wrote the test code.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list