Live data from Hacker News

Avoid exception throwing in performance-sensitive code

lemire.me

241–243 of 243 posts

Re: Avoid exception throwing in performance-sensitive code

#241

Earlier quoted context omitted.

> This is exactly why it's good. How did we manage to get this far before people ~~went insane~~ decided that this is somehow favourable?

After working in an SRE-type role on a codebase full of unchecked exceptions, or exceptions that are caught at the wrong levels because programmers just want their code to work - forcing the explicit handling of errors is favourable because it requires developers to think about what they really want to happen when something goes wrong at this point in the code. Whereas without it, often they will simply catch the exc…

See, you perfectly explain why this is the completely wrong approach.

You have a headache and take painkillers, believing it's going to cure it. No, it doesn't cure the headache, it just masks it out.

The cure is teaching people how to actually program the machines. That's all it takes. Decades of abstraction and piling up more and more nonsense eventually led to the situation we are in now, where people praise bullshit which wouldn't be necessary if people had actually learned how to program the machine and how to do it properly.

Instead people need more and more help to do even the simplest things because they've never learned how to do things the right way. So now idiots require tools preventing them from making mistakes they wouldn't be making if they were properly educated!

Re: Avoid exception throwing in performance-sensitive code

#242

Earlier quoted context omitted.

This is also how errors-as-values work in Rust. Functions that may fail return Result - putting an ? at the end of a failable function call returns T on success, otherwise it propagates E. It reduces result, err := call() if err != nil { return err } to let result = call()?; Completely unobtrusive, but makes failure awareness an obligation.

I know about ? in Rust - the one thing that isn't very clear to me is how often it is enough. That is, with Go, it's quite typical to do something like: result, err := call() if err != nil { return fmt.Errorf("Error while trying to call: %v", err) } Essentially manually building a stack trace. If just doing "return err", you end up with calls to a REST service failing with messages like `couldn't parse "" as int` eve…

There is not (normally) context added automatically. One can use `map_err(|e| ...)` to add context like this:

    let result = call().map_err(|e| SomeError::MoreData(e))?;
Or if using one of the common error libraries to have non-specific error kinds:

    let result = call().context("some data")?;
or

    let result = call().with_context(format!("something happened: {}", other_thing))?;
For something that more directly matches the behavior of the go code, this (using the `anyhow` crate) is a possible match:

    let result = call().map_err(|e| anyhow::Error::msg(format!("Error while trying to call: {:?}", e)?;
Though one would normally avoid this when using anyhow (or in rust in general) as it means we're flattening the error instead of generating a list of causes.

Re: Avoid exception throwing in performance-sensitive code

#243

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…

Branch prediction.
Post reply on HN