Live data from Hacker News

Avoid exception throwing in performance-sensitive code

lemire.me

151–160 of 243 posts

Re: Avoid exception throwing in performance-sensitive code

#151
post #53

Earlier quoted context omitted.

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.

Java is the... uhm... exception here.

That's not how idiomatic C++ is. Nor Rust. Nor Go.

One of Java's (incl standard library) main design flaws is overuse of exceptions.

It should not be emulated. It's too late to fix Java, but that doesn't make it a good idea.

Re: Avoid exception throwing in performance-sensitive code

#152

This post is poorly named. What it's saying is to avoid throwing exceptions for normal flow control, and just use them for exceptional cases (file not found, etc). Performance-sensitive code or not, exceptions for exceptional situations are not going to hinder the app's performance until the exceptional situation becomes common (unless your language does lots of exception setup work on the happy path - which most hav…

It also depends on the language. For example, Python very much operates under the "ask for forgiveness, not permission" mantra, and I even see this used for dict lookups. The number of times I encounter code like this:

  try:
    my_dict[key]
  catch KeyException:
    pass
rather than

  if key in my_dict:
    my_dict[key]
is astounding. I don't know what the performance difference is in Python though.

Re: Avoid exception throwing in performance-sensitive code

#153
post #52

Earlier quoted context omitted.

Returning an option sumtype is also typesafe. Exceptions have to walk up the stack until a suitable handler is found, that handler can't know ahead of time where the value is coming from or if it will ever arrive - just what type it will be if it arrives. Code emitting exceptions also have no knowledge who (if anyone) is going to handle their output. It is a nonlocal goto in reverse. Compared to regular functional re…

> Code emitting exceptions also have no knowledge who (if anyone) is going to handle their output. This is no different from code returning a regular value. When writing `return -EINVAL;` or `return 0, fmt.Errorf("")` or `return Err(something)`, you have no idea who (if anyone) is going to handle your output. Also, one reasonable way of implementing exceptions could be exactly to translate all functions that can thro…

> one reasonable way of implementing exceptions could be exactly to translate all functions that can throw exceptions to functions returning a Result type, and translating function calls to such functions to the equivalent of pattern matching on that return

That's exactly what the lightweight exception proposal for C++ argued for. It additionally used some ABI tricks like storing the discriminant in a flag register when returning from an exception throwing function allowing for very cheap and compact pattern matching.

Re: Avoid exception throwing in performance-sensitive code

#154
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…

Not so much legacy as specifically of the time period where Java was created.

C++ doesn't do this (in the standard library, setting a good tone for idiomatic code).

Older languages don't abuse the exception idea. Nor do newer ones.

(Go is a bad example though, since it took the convenience of Java style exceptions away, but replaced them with nothing)

Re: Avoid exception throwing in performance-sensitive code

#155
post #128

Earlier quoted context omitted.

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.

And it is still opaque where it goes to the programmer when they see it in code. The fact you can use tools to find where it might land (yeah, no shit, you can do same for goto...) is just a mitigation to the problem.

It unwinds the call stack until a catch.

It is the same "problem" as not knowing where a return will return to.

Re: Avoid exception throwing in performance-sensitive code

#156

Earlier quoted context omitted.

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.

Java is the... uhm... exception here. That's not how idiomatic C++ is. Nor Rust. Nor Go. One of Java's (incl standard library) main design flaws is overuse of exceptions. It should not be emulated. It's too late to fix Java, but that doesn't make it a good idea.

Rust uses Result. Checked exceptions are Java's analogue of Result.

Re: Avoid exception throwing in performance-sensitive code

#157

Earlier quoted context omitted.

> It's very hard to write exception safe code in C++. How? As long as RAII is used it's basically for free.

But there are a bunch of codes which are yet to be verified as exception-safe. And in the gaming industry it's often third party code that you cannot even inspect.

The right statement is then that it is very hard to retrofit exceptions in an non-exception safe code base. Exception safety itself is not easy, as it requires different code patterns and idioms than usual.

I believe that those idioms are useful and great even for non-exceptional code, but that's another story.

Re: Avoid exception throwing in performance-sensitive code

#158
post #152

This post is poorly named. What it's saying is to avoid throwing exceptions for normal flow control, and just use them for exceptional cases (file not found, etc). Performance-sensitive code or not, exceptions for exceptional situations are not going to hinder the app's performance until the exceptional situation becomes common (unless your language does lots of exception setup work on the happy path - which most hav…

It also depends on the language. For example, Python very much operates under the "ask for forgiveness, not permission" mantra, and I even see this used for dict lookups. The number of times I encounter code like this: try: my_dict[key] catch KeyException: pass rather than if key in my_dict: my_dict[key] is astounding. I don't know what the performance difference is in Python though.

What about

  thing = my_dict.get(key)
  if thing is None:
      ...

Re: Avoid exception throwing in performance-sensitive code

#159
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…

At least for Go (haven't used Rust), I entirely disagree. After ~3 years of professional programming with the language, `if err != nil` is still constantly annoying me when writing code, but especially and most importantly, when reviewing code. Not to mention, Go has proven conclusively to me that exceptions are exactly the right pattern for error propagation - the 99.9% pattern is "function returns error with messag…

Absolutely. Even after "compressing" my code as much as possible, it looks as if 2/3 of a Go program is pure error handling and no business logic. I just don't understand this militant objection toward exceptions now. Even back in the days of slower virtual machines and crappier hardware, we were fine, and now it's code red! Get rid of exceptions! Performance!

This is in an era of tech where everyone is building BAD distributed systems, with non-optimized databases, a fur ball of slow HTTP queries, and giant payloads. Exceptions are the least of your concerns.

Re: Avoid exception throwing in performance-sensitive code

#160
post #90

Earlier quoted context omitted.

Exceptions work well for 2 kinds of error handling: crash and log, and general retry and log. The second one is more cumbersome with return values if the possible errors originate deep in the stack. Beyond a simple retry, Exceptions are not specific enough for handling errors.

Exceptions are typically custom types - you can build an arbitrarily detailed exception taxonomy (typically branching off the language-standard one), and in most (all?) languages supporting exceptions, you can also give them arbitrary state. You really can't get more specific than that. If exceptions still feel "not specific enough for handling errors", perhaps it's because you're only thinking of most trivial exampl…

You can build a separate exception for every possible raise site. But that is overly burdensome. Moreover, there is no guarantee that any (standard) library calls have an appropriately detailed taxonomy. You could, of course, wrap these library calls and catch exceptions so you can re-raise them yourself. But at that point you are losing the main advantage of exceptions over return values: the ability to separate the happy path from the error-handling path.

To me, once I am building my own expansive taxonomy of exceptions, I am much happier using Optional, or Result/Either type return values.

Post reply on HN