0

During a discussion and some research regarding using exceptions vs returning values, the following caught my mind:

It is cheaper and provides better performance to return a value, whereas throwing an exception requires the creation of a new object and stack unwinding.

Now, I read up on stack unwinding and from my understanding it is the abrupt process of releasing all allocated resources on the current stack frame before jumping back to the next frame on the stack. In Java specifically, no resource is released but instead all objects currently in scope get dereferenced and become eligible for GC. In the case of a graceful return on the other hand, the objects are immediately destroyed due to going out of scope.

The question is this:

Having a method that has declared a small amount of instances (e.g. 3) and assuming that if an exception is thrown, it will be caught on the next level (it won't climb 5 stack levels for example), is there really a noticeable (not sure if this is the correct word to use) difference compared to returning a value, performance wise? I know that at the end of the day in a simple scenario there is not going to be a noticeable difference but could it lead to one in a bigger system?

Please assume that it makes sense to throw an exception in that point in the method (it is an exceptional situation) and it is not for control flow (which is a known mistake). Returning a value would be preferred only for performance reasons.

PentaKon
  • 4,139
  • 5
  • 43
  • 80
  • 2
    Have you tested this? It looks like it should be fairly easy to benchmark, at least crudely... (And yes, I'd expect a significant difference. Aside from anything else, throwing an exception may well require *capturing* the whole of the stack for the exception details, which is a lot more expensive than just returning.) – Jon Skeet Dec 15 '17 at 11:21
  • Re your last paragraph: If it's an exceptional situation, why do you care about the performance of handling it? – T.J. Crowder Dec 15 '17 at 11:25
  • @JonSkeet As far as I know, the stack is captured only if a call to `printStackTrace` or similar method is done, so it can be avoided. I am also expecting a difference but for only 1 stack level I would think it would be minimized (also assuming that I'm not really fearful of leaving objects to the GC). @T.J.Crowder Because if I care a lot about performance, I might trade perfect code clarity for less optimal clarity but more optimal performance. – PentaKon Dec 15 '17 at 11:33
  • @Konstantine: How would the JIT know ahead of time whether `printStackTrace` is going to be called? *Some* information needs to be captured at the time, even if it's not rendered as a string. It still sounds to me like this is something you can and should test for yourself. (And T.J. Crowder's point about it being an exceptional situation is very important.) – Jon Skeet Dec 15 '17 at 11:34
  • Well ideally use something like jmh. – Jon Skeet Dec 15 '17 at 11:38
  • @JonSkeet I'm at work and can't start reading up on JMH but as a first result the following happened: On 5000 iterations (with code warmup), No Exception took 2-3 millis, Checked Exception took 8-12 millis and unchecked took 6-9 millis. – PentaKon Dec 15 '17 at 11:47
  • I'd definitely try to run something for far more than 5000 iterations. Aside from anything else, invoking a method that *just* returns directly 5000 times should definitely not take 2-3ms... I also wouldn't expect to see any difference between checked and unchecked exceptions. – Jon Skeet Dec 15 '17 at 12:05
  • Possible duplicate of [Which part of throwing an Exception is expensive?](https://stackoverflow.com/questions/36343209/which-part-of-throwing-an-exception-is-expensive) – tkruse Dec 16 '17 at 09:12

1 Answers1

0

Consider that to create the Stacktrace of an exception, java does not just go back to the immediate caller. Java goes up all the way to the root stack. So dependening on how deep your small method runs, creating the Stacktrace can be expensive.

Also note this question: Which part of throwing an Exception is expensive?

tkruse
  • 10,222
  • 7
  • 53
  • 80
  • Maybe, but are you sure Java preemptively creates the stack trace or is this operation done only if a method that needs its creation is called? My information says it is lazily created so as long there is no unnecessary call to `.printStackTrace` then that problem is irrelevant – PentaKon Dec 16 '17 at 10:35
  • If you have resources, add them to the question. Here is one benchmark: http://www.nurkiewicz.com/2012/10/where-do-stack-traces-come-from.html. In any case I don't see how this could happen lazily once the stack has unwound. – tkruse Dec 16 '17 at 23:57