Java Forum / General / July 2005
Java Exceptions cause performance hit?
kk_oop@yahoo.com - 13 Jul 2005 16:21 GMT Hi. I wanted to use exceptions to handle error conditions in my code. I think doing that is useful, as it helps to separate "go" paths from error paths. However, a coding guideline has been presented that says "Use conventional error-handling techniques rather than exception handling for straightforward local error processing in which a program is easily able to deal with its own errors."
By "conventional error-handling," I believe they mean returning an error code, or just handling the error without going to a catch block.
When I said that I'd prefer throwing and catching exceptions--and that, in fact, exceptions is the "conventional error-handling technique" in Java, I was told that since we have a real-time system, we can't afford the performance hit caused by using exceptions.
Do exception blocks cause big performance hits? If so, what causes the hit? Or is the person just misinformed?
Thanks for any info,
Ken
Steve Wampler - 13 Jul 2005 16:55 GMT On Wed, 13 Jul 2005 08:21:12 -0700, kk_oop wrote:
> Do exception blocks cause big performance hits? If so, what causes the > hit? Or is the person just misinformed? I don't know how Java implements exception handling, but having done it in another language I would say that the only significant performance hit *should* be the construction of the stack trace (and even there one could argue about the definition of 'significant'...). Plus, the ability of an thrown exception to perform a 'deep return' may help mitigate that cost.
Personally, I think the benefit outweighs the cost, but I could understand someone (especially in a RT system) possibly wanting to cut that cost out - particularly if the stack trace could be turned on/off dynamically).
One wonders, however, what Java version you're using in a real-time system...
Eric Sosman - 13 Jul 2005 17:04 GMT > Hi. I wanted to use exceptions to handle error conditions in my code. > I think doing that is useful, as it helps to separate "go" paths from [quoted text clipped - 13 lines] > Do exception blocks cause big performance hits? If so, what causes the > hit? Or is the person just misinformed? Creating, throwing, catching, and eventually garbage- collecting a Throwable object is certainly a lot more work than a simple `if'. You can measure it for yourself by comparing the time required for two different ways of filling an array:
for (int i = 0; i < array.length; ++i) array[i] = i;
try { for (int i = 0; ; ++i) array[i] = i; } catch (ArrayIndexOutOfBoundsException ex) {}
(This is pretty much the same experiment Joshua Bloch shows in "Effective Java.") On the machine I'm using at the moment, the exception-based approach takes 15.5 times as long as the straightforward loop to fill a 100-element array; that is, one exception takes longer than 1500 limit tests. Your machine may give different timings; try it and see.
Note that the guidance you've been given does not forbid the use of exceptions; it only forbids them for "straightforward local error processing." I suggest you go back to the folks who wrote the guidelines and ask what "straightforward" means; it will probably turn out to be less burdensome than you seem to fear.
 Signature Eric.Sosman@sun.com
Andrea Desole - 13 Jul 2005 17:22 GMT > Note that the guidance you've been given does not forbid > the use of exceptions; it only forbids them for "straightforward > local error processing." I suggest you go back to the folks > who wrote the guidelines and ask what "straightforward" means; > it will probably turn out to be less burdensome than you seem > to fear. Good point. I was just wondering why worry about performance if an exception is for, well, exceptional cases. If an exception is being thrown so often to have a performance impact, either you have a problem with your code or you have a problem with your system. Maybe that person just wants to prevent exception abuse
Cantankerous Old Git - 13 Jul 2005 18:45 GMT >> Note that the guidance you've been given does not forbid >> the use of exceptions; it only forbids them for "straightforward [quoted text clipped - 9 lines] > you have a problem with your system. > Maybe that person just wants to prevent exception abuse I haven't done any testing, so I speak in ignorance, but could it be that setting up the try/catch block is expensive? This will have to happen whether an Exception is actually thrown or not, and will therefore affect error-free performance too.
The Cog
Eric Sosman - 13 Jul 2005 19:13 GMT >>> Note that the guidance you've been given does not forbid >>>the use of exceptions; it only forbids them for "straightforward [quoted text clipped - 14 lines] > have to happen whether an Exception is actually thrown or not, > and will therefore affect error-free performance too. Look at the bytecode, and you'll see that it's very cheap. The cost amounts to one unconditional jump at the end of the `try' clause to skip over the `catch' clause(s). It's possible that the JIT compiler might reorganize the compiled code to eliminate even that much overhead.
 Signature Eric.Sosman@sun.com
Andrea Desole - 14 Jul 2005 08:24 GMT > Look at the bytecode, and you'll see that it's very > cheap. The cost amounts to one unconditional jump at the > end of the `try' clause to skip over the `catch' clause(s). > It's possible that the JIT compiler might reorganize the > compiled code to eliminate even that much overhead. I can imagine. I think that the impact on the performance is basically due to two factors:
1) exception construction (specially the stack, I believe) 2) search for an appropriate exception handler (you have to go through the entire stack until you find one)
Thomas Schodt - 14 Jul 2005 12:04 GMT > I think that the impact on the performance is basically due to two factors: > > 1) exception construction (specially the stack, I believe) Yes, construction of the stack trace is rather expensive.
<http://java.sun.com/j2se/1.5.0/relnotes.html#hotspot>
The compiler in the server VM now provides correct stack backtraces for all "cold" built-in exceptions. For performance purposes, when such an exception is thrown a few times, the method may be recompiled. After recompilation, the compiler may choose a faster tactic using preallocated exceptions that do not provide a stack trace. To disable completely the use of preallocated exceptions, use this new flag: -XX:-OmitStackTraceInFastThrow.
> 2) search for an appropriate exception handler > (you have to go through the entire stack until you find one) Once the exception has been constructed unrolling of the stack (and executing finally blocks) should perform not much different from unrolling of the stack due to return statements.
Andrea Desole - 14 Jul 2005 12:29 GMT >> 2) search for an appropriate exception handler (you have to go through >> the entire stack until you find one) [quoted text clipped - 3 lines] > should perform not much different from > unrolling of the stack due to return statements. Well, what I mean is that, while you are unwinding the stack and executing finally blocks, you also have to check, at every stack frame, if there is a catch block able to handle the exception. But maybe you are right anyway: it shouldn't be a big difference.
Steve Wampler - 14 Jul 2005 15:28 GMT >>> 2) search for an appropriate exception handler (you have to go through >>> the entire stack until you find one) [quoted text clipped - 8 lines] > if there is a catch block able to handle the exception. > But maybe you are right anyway: it shouldn't be a big difference. Gaak. I hope the JVM doesn't unroll the stack. It should be using a simple (internal) hash map to 'jump' directly to the correct catch clause. Yes, that adds a small bit to each try block to adjust the hash map, but most of the work for it can be done at translation time.
Steve Wampler - 14 Jul 2005 15:29 GMT > ...I hope the JVM doesn't unroll the stack. Oops, I meant "unwind", not unroll. Of course the stack is rolled back to some previous point, but shouldn't be an unwinding process.
Steve Wampler - 14 Jul 2005 15:31 GMT > Gaak. I hope the JVM doesn't unroll the stack. Sigh. Ignore me. I forgot about those finally blocks, which force some unwinding...
Andrea Desole - 14 Jul 2005 15:48 GMT > Gaak. I hope the JVM doesn't unroll the stack. It should be > using a simple (internal) hash map to 'jump' directly to the > correct catch clause. Yes, that adds a small bit to each > try block to adjust the hash map, but most of the work > for it can be done at translation time. it's possible that I misunderstand; look at:
http://java.sun.com/docs/books/vmspec/2nd-edition/html/Overview.doc.html#15494
After all, a map like that can be fairly hard to maintain (translation time is probably not enough). Considering that the disadvantage is some less performance when an exception is thrown, I think it makes sense
Ken - 14 Jul 2005 12:30 GMT > > I think that the impact on the performance is basically due to two factors: > > > > 1) exception construction (specially the stack, I believe) > > Yes, construction of the stack trace is rather expensive. Is this price paid at run time only when an exception is actually thrown? Or does simply having a try/catch block or a throw statement in the java code cause this to happen at run time even when an exception is not thrown?
Thanks!
Ken
Andrea Desole - 14 Jul 2005 12:33 GMT > Is this price paid at run time only when an exception is actually > thrown? Or does simply having a try/catch block or a throw statement > in the java code cause this to happen at run time even when an > exception is not thrown? when the exception is not thrown is not constructed, so there is no problem
John Currier - 14 Jul 2005 03:05 GMT Eric, your "performance comparison" is slightly skewed. The performance characteristics of the two approaches is highly dependent on the number of iterations and the cost of checking for the terminating condition. In your comparison the number of iterations (100) times the cost of checking (i < array.length) is extremely small compared to the cost of creating and throwing the exception. There are many scenarios where the opposite is true.
John http://schemaspy.sourceforge.net
Eric Sosman - 14 Jul 2005 17:14 GMT > Eric, your "performance comparison" is slightly skewed. The > performance characteristics of the two approaches is highly dependent [quoted text clipped - 3 lines] > compared to the cost of creating and throwing the exception. There are > many scenarios where the opposite is true. It's usually considered a good idea to quote a few snippets from the message you're replying to, in order to give people some context. Keep in mind that propagation of messages on Usenet is irregular and unsynchronized; it's likely that some readers see your reply but do not see my message, and have no idea what you're writing about.
To bring people up to date: A question asked about the performance cost of using exceptions. I answered with a simple illustration cribbed from "Effective Java" by Joshua Bloch, showing two ways to loop through an array: one in which the index is compared to the array length at each iteration, and another where the loop simply runs until it provokes ArrayIndexOutOfBoundsException, which is caught. I also reported that on my machine the latter was some 15.5 times slower than the former on a 100-element array, and invited the questioner to make his own measurements.
Now that we're all up-to-date ...
John, I'd be surprised to learn that there are "many scenarios" where using exceptions for control flow is faster than using more direct methods like `if'. It might be possible to concoct such a scenario, but I think it would be difficult. Consider: if the exception reports the same circumstance that the `if' or whatever would have tested, the code that decides to throw the exception must itself make the same test[1]. If the `if' made the same test, the code could discover the condition without the overhead of creating and processing the exception object.
Of course, there's always the possibility of poor design. Bloch points to Iterator.hasNext() in this regard: the method is unnecessary in the sense that Iterator.next() will throw NoSuchElementException when it "runs off the end," so a `try' block could accomplish all the decision-making that hasNext() enables.[2] So why does hasNext() exist? Because it's gobs more efficient and requires less typing, that's why. If you're confronted with an API designed by someone who hasn't taken this lesson to heart, an API that offers the "moral equivalent" of next() without a matching hasNext(), you have little choice but to use what you're given -- and curse the designer.
Now, observe that next() must somehow make a test that's equivalent to hasNext(), so the standard idiom for iteration winds up making the test twice. If that test were expensive (which it isn't for Iterator, but let's imagine some other API offering such a pair of methods), it's just possible that the cost of processing an exception might be smaller than the cost of making two tests. My informal measurement gives some rough idea of how expensive a test would need to be before using exceptions became a practical alternative -- and the answer is "very expensive indeed," more than the cost of 1500 integer-comparing `if's. I made no claim that this measurement was highly accurate or was universal, but I'd be comfortable with saying that the cost of one exception lies somewhere North of a thousand simple `if' tests.
Yes, it's possible to write an expensive `if', most simply by calling a few expensive methods inside it. I suggest that such tests are not typically associated with exceptions: you simply don't see code that calls BigInteger.probablePrime() and throws an exception based on the result. (Or if you do, you're looking at code unlike anything I've seen ...) If you find "many scenarios" of this sort in the code you work with, you have my sincerest sympathy.
[1] Or an equivalent test. If the equivalent is cheaper than the original, one wonders why the `if' would make the costlier test in the first place.
[2] Or almost. Bloch points out that it's difficult to distinguish the "expected" exception when next() runs off the end from an "unexpected" exception thrown because of a bug somewhere in code executed elsewhere with the loop. A simple try/catch around the whole loop lumps both together, whereas hasNext() can easily tell the two conditions apart.
 Signature Eric.Sosman@sun.com
Steve Wampler - 14 Jul 2005 19:05 GMT > John, I'd be surprised to learn that there are "many > scenarios" where using exceptions for control flow is faster > than using more direct methods like `if'. It might be possible > to concoct such a scenario, but I think it would be difficult. Simply bumping your test from an 100 element array to a 50000 element array gives one: ===================================================== ->java -version java version "1.5.0_02" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_02-b09) Java HotSpot(TM) Client VM (build 1.5.0_02-b09, mixed mode) ->cat Foo.java import java.util.Date;
public class Foo { public static void main(String args[]) { int array[] = new int[50000];
long t1 = new Date().getTime(); for (int i = 0; i < array.length; ++i) { array[i] = i; } long t2 = new Date().getTime();
long t3 = new Date().getTime(); try { for (int i = 0; ; ++i) { array[i] = i; } } catch (ArrayIndexOutOfBoundsException ex) {} long t4 = new Date().getTime();
System.out.println("T1 : "+(t2-t1)+"ms"); System.out.println("T2 : "+(t4-t3)+"ms"); } } ->javac Foo.java ->java Foo T1 : 5ms T2 : 1ms ===================================================== Granted, I think it's an odd way to program, but it certainly wasn't hard to construct...
Eric Sosman - 14 Jul 2005 19:58 GMT >> John, I'd be surprised to learn that there are "many >>scenarios" where using exceptions for control flow is faster [quoted text clipped - 6 lines] > T1 : 5ms [for ordinary loop] > T2 : 1ms [infinite loop with try/catch] Um, er, I wouldn't even time a C code construct this way, never mind a piece of Java. The time taken for just one execution of a small piece of code simply isn't to be trusted, especially not if it's the very first execution. GC doesn't run, the JIT compiler doesn't run -- it's like predicting someone's Marathon time by checking his crawling speed in infancy.
Even in my first quick-and-dirty trial, I ran each loop a thousand times to "warm up" the JVM, then timed each loop on one thousand, ten thousand, ... repetitions until the ratio of times settled down.
> Granted, I think it's an odd way to program, but it certainly > wasn't hard to construct... All right, you got me: I didn't think about the situation enough. With a 50000-element array (and with warm-ups and repetitions as described above), using an exception is about 7% faster than making comparisons. Specifically, I got 22855 vs. 21303 milliseconds for ten thousand repetitions of the two loops (that's one billion array-element stores in all). So now we've got two rough measurements of exception-processing overhead: one exception costs as much as somewhere between 1500 and 47000 integer comparisons. (The wide range isn't to be wondered at: we're just rediscovering the fact that the derivative of 1/x is large when x is small. Of the two measurements, I'd place a bit more faith in the latter.)
 Signature Eric.Sosman@sun.com
Steve Wampler - 14 Jul 2005 20:19 GMT > .. > With a 50000-element array (and with warm-ups and [quoted text clipped - 8 lines] > derivative of 1/x is large when x is small. Of the two > measurements, I'd place a bit more faith in the latter.) So would I, in fact, I suspect the 47000 is pretty close to being spot on. Increasing the array size beyond 50000 is probably not going to show much change. Of course, that's also a minimal exception cost. I'll bet the cost goes up if the test is run in a more deeply nested call stack...
Raymond DeCampo - 14 Jul 2005 20:06 GMT >> John, I'd be surprised to learn that there are "many >>scenarios" where using exceptions for control flow is faster [quoted text clipped - 41 lines] > Granted, I think it's an odd way to program, but it certainly > wasn't hard to construct... I think you will both have to work harder to prove anything. I got similar results when I ran the code above. However, if I reversed the order of the experiments, I got the opposite results:
======================================================= $ java -version java version "1.5.0_03" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_03-b07) Java HotSpot(TM) Client VM (build 1.5.0_03-b07, mixed mode, sharing) $ cat Foo.java import java.util.Date;
public class Foo { public static void main(String args[]) { int array[] = new int[50000];
long t3 = new Date().getTime(); try { for (int i = 0; ; ++i) { array[i] = i; } } catch (ArrayIndexOutOfBoundsException ex) {} long t4 = new Date().getTime();
long t1 = new Date().getTime(); for (int i = 0; i < array.length; ++i) { array[i] = i; } long t2 = new Date().getTime();
System.out.println("T1 : "+(t2-t1)+"ms"); System.out.println("T2 : "+(t4-t3)+"ms"); } } $ java -cp . Foo T1 : 1ms T2 : 14ms =========================================================
Ray
 Signature XML is the programmer's duct tape.
Steve Wampler - 14 Jul 2005 20:26 GMT > I think you will both have to work harder to prove anything. I got > similar results when I ran the code above. However, if I reversed the > order of the experiments, I got the opposite results: Yes, my 'micro-benchmark', as Eric also points out, doesn't show much. Eric's latest measures are much better.
John Currier - 15 Jul 2005 01:44 GMT Partial quote...sorry, I thought that threading newsreaders were the norm:
> Now, observe that next() must somehow make a test that's > equivalent to hasNext(), so the standard idiom for iteration [quoted text clipped - 3 lines] > the cost of processing an exception might be smaller than the > cost of making two tests. I'm not sure how you can quantify the performance characteristics of Iterator when it's an interface.
Comparing the cost of creating/throwing an exception to the cost of making two tests is not relevant without knowing the number of iterations. That cost of the exception is fixed plus the cost of one test times the number of iterations. The alternative approach is the cost of two tests times the number of iterations. Which approach has more desireable scalability characteristics? Yes, the number of iterations might have to be relatively high to see a benefit, but that depends on the performance characteristics of all the pieces involved.
Note that I don't use the exception approach, but I wouldn't blindly dismiss its appropriateness for a particular scenario.
John
Paul Bilnoski - 13 Jul 2005 17:13 GMT > When I said that I'd prefer throwing and catching exceptions--and that, > in fact, exceptions is the "conventional error-handling technique" in [quoted text clipped - 3 lines] > Do exception blocks cause big performance hits? If so, what causes the > hit? Or is the person just misinformed? The problem with exceptions in hard real-time systems is that it introduces more invariants with respect to the expense of execution. It becomes more difficult to make guarantees about time and memory used, so I think that may be why it is preferred against when you can use something conventional in simpler cases. There may be some threshold of complexity where you opt for an exception over checking flags or error codes. There is a similar problem with garbage collection and making running time more predictable that RT implementations account for. --Paul
Robert Klemme - 13 Jul 2005 17:48 GMT >> When I said that I'd prefer throwing and catching exceptions--and >> that, in fact, exceptions is the "conventional error-handling [quoted text clipped - 4 lines] >> Do exception blocks cause big performance hits? If so, what causes >> the hit? Or is the person just misinformed? A thrown exception causes the hit. IMHO the penalty in the normal case (no exception thrown) is neglectible.
> The problem with exceptions in hard real-time systems is that it > introduces more invariants with respect to the expense of execution. [quoted text clipped - 5 lines] > There is a similar problem with garbage collection and making running > time more predictable that RT implementations account for. As far as I understand the term "real time system" I wonder why someone uses Java in the first place. There is no such thing as guaranteed response times etc. So maybe the OP is dealing with a soft real time system.
http://en.wikipedia.org/wiki/Real-time_system
Regards
robert
Paul Bilnoski - 13 Jul 2005 17:58 GMT >>>When I said that I'd prefer throwing and catching exceptions--and >>>that, in fact, exceptions is the "conventional error-handling [quoted text clipped - 28 lines] > > robert I used Java for a few real-time system programming projects in college. We had a RT Linux kernel and the distributor also provided an RT Java VM implementation though it was not the full language (no 1.4 NIO, no Swing). There was also some extra functionality for the GC system to make it handle in a more predictable way.
But to answer your point of "why use Java": because it is more comfortable to program multithreaded applications than with some C++ threading libraries, among other things. --Paul
Casey Hawthorne - 13 Jul 2005 18:25 GMT Exceptions have performance penalties when thrown, only minor when not thrown! Depending upon how you define "minor"!
The challenge with exceptions is maintaining global state, like: - cursor state - timing state in real-time systems
-- Regards, Casey
Joan - 13 Jul 2005 19:21 GMT > Hi. I wanted to use exceptions to handle error conditions in my code. > I think doing that is useful, as it helps to separate "go" paths from > error paths. However, a coding guideline has been presented that says > "Use conventional error-handling techniques rather than exception > handling for straightforward local error processing in which a program > is easily able to deal with its own errors." The key is "easily able to deal with its own errors." If it ain't easy, use toss/catch (if you want.)
> By "conventional error-handling," I believe they mean returning an > error code, or just handling the error without going to a catch block. [quoted text clipped - 10 lines] > > Ken Matt Atterbury - 15 Jul 2005 04:07 GMT I'm surprised no-one else has commented on/noticed this ...
> Hi. I wanted to use exceptions to handle error conditions in my code. > I think doing that is useful, as it helps to separate "go" paths from [quoted text clipped - 10 lines] > Java, I was told that since we have a real-time system, we can't afford > the performance hit caused by using exceptions. I'm confident that whatever your system is, it is _not_ real-time. Your superiors might think it's "time-critical" or even "pseudo-real-time" but that's as far it could go in Java as I'm pretty sure it is impossible to code a real-time system in Java since, AFAIK, you do not have access to real-time clocks and hardware interrupts. And, I would be absolutely amazed if you guys even went to trouble of coding your Java program using a "true" real-time design (but, hey, amaze away :-).
m.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|