> In .NET and Java it costs at least 100x as much time to throw an exceptions as to return an error code.
Don't know about .NET but in Java it is not throwing exceptions that is heavy but filling in stack trace during construction of a Throwable.
It can be made much more performant using constructor that disables stack trace: https://docs.oracle.com/en/java/javase/21/docs/api/java.base...
In the margin, branches are more likely close to the hot path, so they are more likely to 'pollute' the instruction cache. Whilst exceptions have less of this.
Though profile guided optimization will probably catch this. And it might be that even without, compilers still optimize around this.
You pay the cost only when the exception is raised. If that happens on more than 1% of your runtime checks, it probably is not (aka should not be) an exception.
In .NET and Java it costs at least 100x as much time to throw an exceptions as to return an error code.
Other languages may have cheaper exceptions, but for many mainstream languages, you pay a big performance price for exceptions.
That price is often offset by other positive things, so the tradeoff is made willingly and with eyes open.