Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The thing with programming language evolution is that quite often everything except the error handling gets faster over time. If you have an app that makes aggressive use of errors, you’re not going to see the same speedups from version to version that others are seeing.

Particularly in JITed languages, if the multiplier is hyperbole today, there may be a day in the future where it’s accurate.



> The thing with programming language evolution is that quite often everything except the error handling gets faster over time.

Funny I was just reading this the other day : https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotn...

It's probably not the first thing you spend effort on when optimizing but it gets better over time.


The minimum cost of an error is one cold branch. Which is effectively free on the happy path, and as cheap as it possibly can be on the error path.

A well-designed error handling system can feasibly reach this goal, at which point no more optimization is possible.

Edit @hinkley: I am unfortunately in hacker jail, and have used up my post quota, so I have to edit my post rather than reply to yours. Reply follows.

Throwing, the way Java and C++ do it, exceeds the minimum cost of an error, yes. Not that this is some sort of show-stopping problem, I'm discussing the minimum cost, not what level of cost makes errors too expensive.

A branch-not-taken, which is the opposite of processing an error, caught or otherwise, is what I described as practically free. Not always. If the only path forward is, for instance, to reference a pointer, and the error would mean that the pointer is a null pointer, the chip would have to wait for the branch to coalesce, which might mean a minor pipeline stall.

But if the processor can do further work, such as checking for an error on malformed input, where it's legal to speculatively execute the next decode on the predicted branch, it really is practically free. It costs considerably less than one instruction. If the branch triggers, the processor spills all the speculative work and switches. Since errors are expected less frequently than success, more or less by definition, that's the correct tradeoff.

This is why I described the error branch as "cold". The processor should predict and speculate on the happy path.

Zig is an example of a language where errors can be as inexpensive as a superscalar check on a given register while the main path moves forward. This is also possible in C when checking errno(). I can't speak for Rust, but enormous amounts of work have gone into that compiler, and it should indeed be possible to compile a match-on-Result to the same efficient level. Perhaps trickier since Rust doesn't "know" what an error is, but I suspect that in practice it can get this right.

Not that it's even mostly up to the compiler: there are ASM hints for the branch predictor in some instruction sets, but modern branch predictors don't need those to handle the case where 99+% of the time execution proceeds on one branch. It's conventional for compilers to emit "branch on cold, proceed on hot", but it's been a long time since that has mattered for execution speed. You'll get a bit tighter on a chip with no predictor and a shallow pipeline, like AVR, but for anything which can run an operating system it's almost irrelevant now.

I see no a priori reason why Go shouldn't achieve the minimum level either. Languages which use exceptions and try/catch must do some bookkeeping, which imposes a cost on the code whether an exception is raised, or not. That can be minimized, but not to the limit I'm talking about.

You might find this link interesting: https://ziglang.org/documentation/0.12.0/#Implementation-Det...

Note that the costs described are for the ability to generate an error trace, not error handling itself. This cost is only paid in debug and ReleaseSafe modes.


Are you talking about errors that are not thrown? What language are you using where catching and processing an error are free?


Only exceptions are thrown. Errors are not necessarily exceptions.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: