A bare minimum Catalyst action can handle about 100 requests per second on my machine last I checked. Another old measurement places Plack at about 2K on the fastest backends, with absolutely bare minimum request handling.
Most of the real world applications I wrote can handle about 10-20 requests per second on my machine for the quickest dynamic requests.
confess, Throwable::Error, Exception::Class and creating a hash with 100 pairs of short strings are all in the range of 2K-5K iterations per second.
Devel::StackTrace and croak break the 10K iterations per second barrier.
It would take about 100 Devel::StackTrace->new calls per HTTP request to make my real world apps 5% slower, but 10 stack frames deep, it would only take 50 calls to have the same impact.
Try::Tiny clocks in at 70K string errors per second. A plain eval with the same error does 490K. With an anonymous hash reference (no string formatting), it goes up to 1.2M iterations.
That means that you could only catch that many errors per second, if that's all you ever did. Since exceptions are the exception, not the rule, that probably doesn't matter much.
An inlined Moose for a class with no attributes can only generate 240K objects per second.
I suspect that in a real world web request that probably makes several thousand subroutine or method calls, allocates data structures, talks to a database, deserializes and parses strings, validates input, creates objects etc, even something like 20-30 exception objects would simply not make that big a difference.