I did some basic tests in sample programs and there doesn't seem to be much of a difference. I so much prefer the finally way of doing this - but I was wondering if it will cause any performance hit in a big project.

It's not really worth posting as an answer, but no. If you're using Java, which expects exceptions to be the default error handling strategy, then you should use try/catch/finally - the language is optimized for the pattern you are using.
–
Jonathan RichSep 4 '13 at 13:22

Write code cleanly in such a way that it expresses what you're trying to accomplish. Optimize later when you know you have a problem - don't avoid language features because you think that you might shave a few milliseconds off of something that isn't slow in the first place.
–
Sean McSomethingSep 4 '13 at 23:40

@mikeTheLiar - If you mean that I should write if(!cond), then it's java which made me do this. In C++, that's how I write code both of booleans and also for other types - i.e. int x;if(!x). Since java allows me to use this only for booleans, I have totally stopped using the if(cond) & if(!cond) in java.
–
user93353Sep 7 '13 at 0:49

1

@user93353 that makes me sad. I would much rather see (someIntValue != 0) than comparing rather than evaluating booleans. That smells to me, and I refactor it immediately when I see it in the wild.
–
mikeTheLiarSep 7 '13 at 12:23

5 Answers
5

As indicated in How slow are Java exceptions? one can see that the slowness of try {} catch {} is within the instatiation of the exception itself.

Creating an exception will fetch the entire call stack from the runtime and this is where the expense is. If you are not creating an exception, this is only very slightly an increase of time.

In the example given in this question there aren't any exceptions, one wouldn't expect any slowdown from creating them - they aren't created. Instead, what is here is a try {} finally {} to handle resource deallocation within the finally block.

So to answer the question, no, there is no real runtime expense within a try {} finally {} structure that doesn't use exceptions (it isn't unheard of, as seen). What is possibly expensive is the maintenance time when one reads the code and sees this not typical code style and the coder has to get their mind around that something else happens in this method after the return before returning to the previous call.

As has been mentioned, maintenance is an argument for both ways of doing this. For the record, after consideration, my preference would be the finally approach.

Consider the maintenance time of teaching someone a new language structure. Seeing try {} finally {} isn't something that one often sees in Java code and thus can be confusing to people. There is a degree of maintenance time for learning a bit more advanced structures in Java than what people are familiar with seeing.

The finally {} block always runs. And this is why you should use it. Consider also the maintenance time of debugging the non-finally approach when someone forgets to include a logout at the proper time, or calls it at the improper time, or forgets to return / exit after calling it so that it is called twice. There are so many possible bugs with this that the use of try {} finally {} makes impossible to have.

When weighing these two costs, it is expensive in maintenance time not to use the try {} finally {} approach. While people can dicker about how many fractional milliseconds or additional jvm instructions the try {} finally {} block is compared to the other version, one must also consider the hours spent in debugging the less than ideal way of addressing resource deallocation.

Write maintainable code first, and preferably in a way that will prevent bugs from being written later.

An anon-suggested edit said thus: "try/finally offers guaranties you wouldn't have otherwise regarding runtime exceptions. Whether you like it or not, any line is virtually capable of throwing an exception" - Me: which isn't exactly true. The structure given in the question doesn't have any additional exceptions that would slow down the performance of the code. There are no additional performance impacts by wrapping a try/finally around the block compared to the non-try/finally block.
–
MichaelTSep 4 '13 at 15:52

2

What could be even more expensive in maintenance than understanding this use of try-finally, is having to maintain several clean-up blocks. Now at least you know that if additional clean-up is needed, there is only one place to put it.
–
Bart van Ingen SchenauSep 4 '13 at 17:06

@BartvanIngenSchenau Indeed. A try-finally is probably the best way to handle it, it just isn't that common of a structure that I've seen in code - people have enough trouble trying to understand try catch finally and exception handling in general.. but try-finaly without a catch? What? People really don't understand it. As you suggested, it is better to understand the language structure than trying to avoid it and do things poorly.
–
MichaelTSep 5 '13 at 0:56

I mostly wanted to make it known that the alternative to try-finally isn't free either. I wish I could give another upvote for your addition about the costs.
–
Bart van Ingen SchenauSep 5 '13 at 16:02

The quick answer is that there is no significant performance hit from using try/finally blocks. There is a performance hit when you throw and catch exceptions.

The longer answer is to see for your self. If you look at the underlying CIL code generated (e.g red-gate reflector then you can see the underlying CIL instructions generated and see the impact that way.

To complete your answer Java 7 introduced a try-with-resources statement that would be akin to your .net using construct, assuming that the resource in question implements the AutoCloseable interface.
–
haylemSep 4 '13 at 13:28

I would even remove this ret variable, which is just assigned twice to be checked one line later. Make it if (dosomething() == false) return;.
–
ott--Sep 4 '13 at 15:08

Agreed but I wanted to keep the OP code the way it was provided.
–
MichaelSep 4 '13 at 15:27

@ott-- I assume the OP's code is a simplification of their use case - for example, they might have something more like ret2 = doSomethingElse(ret1), but that's not relevant to the question so it was removed.
–
IzkataSep 4 '13 at 16:12

if (dosomething() == false) ... is bad code. Use the more intiutive if (!dosomething()) ...
–
Steffen HeilDec 17 '14 at 8:01

The accepted answer on this question shows wrapping a function call in a try catch block costs less than 5% over a bare function call. Actually throwing and catching the exception caused runtime to balloon to more than 66x the bare function call. So if you expect the exception design to throw regularly then I would try to avoid it (in properly profiled performance critical code), however if the exceptional situation is rare then it isn't a big deal.

"if the exceptional situation is rare" - well there's a tautology right there. Exceptional means rare and that's precisely how exceptions should be used. Never should be part of the design or control flow.
–
Jesse C. SlicerSep 4 '13 at 14:07

1

Exceptions are not necessarily rare in practice, it's just accidental side effect. For example if you have bad UI people might cause the exception use case flow more often than the normal flow
–
EsailijaSep 4 '13 at 14:21

1

There are no exceptions being thrown in the question's code.
–
MichaelTSep 4 '13 at 14:49

1

@JesseC.Slicer There are languages where it is not uncommon to see them used as flow control. As an example when iterating anything in python the iterator throws a stopiteration exception when it is done. Also in OCaml their standard library seems to be very "throw happy", it throws in a large number of situations that aren't rare(if you have a map and try to look up something that doesn't exist in the map it throws).
–
stonemetalSep 4 '13 at 15:07

@stonemetal As does a Python dict, with a KeyError
–
IzkataSep 4 '13 at 16:17

As others already noted, Ttese code will have different results, if either dosomethingelse or dootherstuff throw an exception.

And yes, any function call can throw an exception, at least a StackOVerflowError! While it is rarly possible to handle these correctly (as any called cleanup function will probably have the same issue, in some cases (such as implementing locks for example) it is crucial to even handle that correctly...