Live data from Hacker News

Avoid exception throwing in performance-sensitive code

lemire.me

111–120 of 243 posts

Re: Avoid exception throwing in performance-sensitive code

#111
I’m curious if there are ecosystems where get_positive_value would be a reasonable name for the method described. I’d expect something like assert_positive, or check_is_positive, or throw_if_negative. I admit these would suggest returning void rather than int, but “get” just isn’t right either in the ecosystems I’m familiar with (e.g. Rust, Python, JavaScript).

Re: Avoid exception throwing in performance-sensitive code

#112

Earlier quoted context omitted.

"Exceptions should be... the exception." :)

The problem is exceptions have entirely opaque flow control. They're the opposite of a goto statement: a comes-from statement if you will. Flow control could originate literally anywhere down the stack and that makes reasoning about what's happening very difficult. Depending on the language it can also have a super broad and ever-changing surface area.

This is not correct, a “comes-from” statement would still be the same behavior as a goto except it’s defined at the label and there is no “goto” at the departure line.

Exceptions are just “goto whatever catch is in the call stack”.

It’s still completely obvious when you see a throw statement that it can throw, and static analysis can tell you exactly what can be thrown by each function.

Re: Avoid exception throwing in performance-sensitive code

#113

Earlier quoted context omitted.

Is that still true in recent Python versions? Sounds like low-hanging fruit for perf optimisation.

Python 3.11 made the "try" part of exceptions zero-cost. The "except" part only has overhead if the exception is triggered.

So the answer to the question is yes, because for loops signal their finishing by raising an exception.

Re: Avoid exception throwing in performance-sensitive code

#114
post #43

Exceptions are starting to feel like a legacy programming paradigm to me. Rust & Go have, at least in a practical programming context, shown that errors-as-values has far less footguns and encourages better error handling practices than exceptions, which often are treated as an afterthought or end up being abused like in this post. Whenever I'm writing Python or Java I can't help but feel anxious about calling a func…

Rust do still has exceptions, they're just called "results". You can't really have values as exceptions unless you plug a lot of ad-hoc constructs into your language so that they eventually become similar to exceptions [1]: > Add syntactic sugar for working with the Result type which models common exception handling constructs. The whole error handling story with Rust can be summarized as "we have results but want to…

No! Exceptions have a very well defined meaning. Exceptions in Rust are non-aborting panics.

Re: Avoid exception throwing in performance-sensitive code

#115

Earlier quoted context omitted.

In Go the programmer is forced to make a decision on what to do with the error. Common patterns include (A) return an annotated error, (B) log it and continue, (C) retry, (D) aggregate the errors in some way. If you believe the only way to handle an error is (A), then Go's design makes no sense.

You seem to believe options B to D are not available to programmers in languages with exceptions. The real value comes from making option E much more unlikely: ignoring both the result and error value altogether, because you relied on the side effect of the function you called.

You might like how Rust does error handling. Rather than a function returning a triple of (val, error) where the error can be ignored, functions return Result. If you want to get the T, you must write code that handles both possibilities. If your function instead wants the T and propagate the E upwards if it exists, you can do that with one character - “?”

Re: Avoid exception throwing in performance-sensitive code

#116

Not having exception is not having incorrect code i.e. code that does not throw. This is very hard to do in languages that naturally throws exception like Java or C/C++. If you have errors as part of the contract however...now you can be sure (or surer) that the function you are calling does not fail.

I think most serious C++ shops are probably compiling with -fno-exceptions.

That is entirely false. You can barely even use half the language without exceptions.

Re: Avoid exception throwing in performance-sensitive code

#117
post #28

Earlier quoted context omitted.

Which is not to suggest you should be using exceptions for flow control.

Python's StopIteration has entered the chat.

I remember reading a long time ago that cpython had done some work to make exceptions lightweight enough for it to be reasonable to use them for control flow... No idea what that was though.

Re: Avoid exception throwing in performance-sensitive code

#118
post #22

Impossible to avoid in python.. exceptions are even how a simple for loop is implemented under the covers!

Is that still true in recent Python versions? Sounds like low-hanging fruit for perf optimisation.

Yes, the for loop still calls next() on the iterator until it throws a StopIteration exception.

Re: Avoid exception throwing in performance-sensitive code

#119
post #53

Earlier quoted context omitted.

I must admit I use exceptions heavily for validation, e.g. checking input at API bounds. It makes the code fairly clean. I would imagine this is considered bad practice, but if there was no overhead this seems preferable over wrapping every call in some wrapper object. Any good links to further info on this?

Food for thought: what are the expected consequences of the exception? If the error will stop the program flow and show a warning dialog to the user, it's useless to think too much about performance. More or less the same if it's going to log some message and abort the operation. What is usually frowned upon is using the exception as a kind of goto for normal flow of the program. Exceptions should be... the exception…

Exception is a way to return from a function abnormally. So yes, they are for exceptional conditions. IMO it's perfectly fine to use them for input validation. The Java standard library itself does it all the time.

Re: Avoid exception throwing in performance-sensitive code

#120

I'm completely ignorant of the subject, but most surprising to me in his example was that the compiler didn't optimize away the inefficiency. Is there something about exception handling that makes it not get taken into account during optimization?

Exceptions in all modern C++ compilers are implemented in a way that prioritizes the performance of cases where an exception is NOT thrown at the cost of performance when an exception is thrown. Note that this means C++ code should be slightly faster than equivalent C/Go/Rust-style code that has to do an if/else after every function call that can fail to check if it did.

Once this decision was made, investing time in optimizing programs that use exceptions for regular control flow became very very low in the priority list of all C++ compilers. This would include recognizing cases where an exception could be replaced with a single if/else, and optimizations for the unhappy path in general.

Post reply on HN