Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the cost of reraising an exception?

Is this

try
  DoSomethingThatMightThrowAnException;
except
  on E : ESyntaxError do
    begin
    if (E.ErrorCode = errMissingBracket) then
      HandleError
    else
      raise;
    end;
end;

slower than this?

try
  DoSomethingThatMightThrowAnException;
except
  on E : EMissingBracketSyntaxError do
    begin
    HandleError;
    end;
end;

What's the difference to be expected? Does it matter? Note that this could happen several times through the call stack.

like image 501
jpfollenius Avatar asked Jun 22 '11 10:06

jpfollenius


3 Answers

What's the difference to be expected?

The difference between the scenarios you described is minimal.
However there is a signifcant difference between raising an exception and not raising one at all (using error results).

Does it matter? Note that this could happen several times through the call stack.

You should only use exceptions for "exceptional situations". If the error is frequent, especially for example in a loop then it deserves to be elevated to a fully fledged use-case scenario.

If you don't do this, what starts out seemingly simple, quickly deteriorates into a situation where your except block becomes bigger than the rest of your routine.

Ordinarily it should be quite trivial to check the condition and deal with it as an explicit branch in main-line code.

I.e. instead of:

begin
  try
    //Do1
    //Do2 (possibly raising an exception that you can handle)
    //Do3
    //Do4
  except
    //Dealing with main-line cases in exception handlers is
    //very bad, leading to difficult to read code in the future.
  end;
end;

Rather write:

begin
  //Do1
  //LDo2Result := Do2
  //NOTE: Do2 can still raise exceptions in EXCEPTIONAL situations.
  //  But for "main-line" use-case scenarios should rather return explicit 
  //  results that can be handled.
  if LDo2Result = d2rNoErrors then
  begin
    //Do3
    //Do4
  end;
  if LDo2Result = d2rBracketMissing then
  begin
    //DoX
  end;
end;

The above is generally better in both performance and maintainability than either of the scenarios you describe. However, as with all things software development related: you get a pallette of guidlines and techniques, but you need to apply your experience to choose "the best tool for the specific job currently at hand".

like image 134
Disillusioned Avatar answered Nov 17 '22 02:11

Disillusioned


Unless your program's logic severely relies on exceptions (which is probably a sign of bad design) I think it will hardly matter since exception handling will only be 0.5% of the cpu time your application takes.

But taking a wild guess, I don't think there will be much of a performance difference, since internally the exception will be passed on either way.

On the other hand, I prefer the second method a lot more since you are expressing what you want syntacticly in the language, which is good. But I understand that method one can be preferred in some cases, especially when the context is bigger and more complex.

Disclaimer: I have never programmed in Delphi and I know nothing about the internals of the language. There might as well be a huge difference in performance, I don't know.

like image 42
orlp Avatar answered Nov 17 '22 03:11

orlp


The performance difference is negligible in the context of a real-world application. On my machine raising and handling an exception (with a null handler) takes about 0.3 milliseconds, and if I add extensive logging, abut 1.3 milliseconds. So if the exceptions are truly exceptional, it will not make one jot of difference to your application's performance.

like image 1
Misha Avatar answered Nov 17 '22 03:11

Misha