While perhaps not so extreme, I have found similar behaviour in C++. I worked on a code base where there was a really nice way of writing an algorithm which would 'throw' around 100,000 times/sec, and we had to change to something like this (keep checking return values of functions, and return if they are true), to get reasonable performance.
Most C++ ABIs use something called zero cost exceptions where the performance of the uncommon "throws" path is made much slower so that introducing a try/catch block has no performance penalty when no exception occurs. For details, see LLVM's docs on the matter: http://llvm.org/docs/ExceptionHandling.html
The C++ philosophy has always been that exceptions are for truly exceptional situations, not a tool for regular flow control. Consequently, practically all C++ implementations optimize heavily for the non-exceptional case - try/catch blocks are almost free as long as nothing gets thrown.
Comments
While perhaps not so extreme, I have found similar behaviour in C++. I worked on a code base where there was a really nice way of writing an algorithm which would 'throw' around 100,000 times/sec, and we had to change to something like this (keep checking return values of functions, and return if they are true), to get reasonable performance.
Most C++ ABIs use something called zero cost exceptions where the performance of the uncommon "throws" path is made much slower so that introducing a try/catch block has no performance penalty when no exception occurs. For details, see LLVM's docs on the matter: http://llvm.org/docs/ExceptionHandling.html
The C++ philosophy has always been that exceptions are for truly exceptional situations, not a tool for regular flow control. Consequently, practically all C++ implementations optimize heavily for the non-exceptional case - try/catch blocks are almost free as long as nothing gets thrown.