Skip to content

Instantly share code, notes, and snippets.

@nothingmuch
Created July 6, 2010 21:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nothingmuch/465959 to your computer and use it in GitHub Desktop.
Save nothingmuch/465959 to your computer and use it in GitHub Desktop.

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.

use strict;
use warnings;
use Benchmark qw(cmpthese);
use Carp;
use Devel::StackTrace;
use Try::Tiny;
use Throwable::Error;
use Error;
use Exception::Class 'MyException' => { fields => [ qw(foo) ] };
{
package Foo;
use Moose;
with qw(Throwable);
__PACKAGE__->meta->make_immutable;
package Empty;
use Moose;
__PACKAGE__->meta->make_immutable;
}
sub foo { bar(@_) }
sub bar { gorch(@_) }
sub gorch { baz(@_) }
sub baz { quxx(@_) }
sub quxx { lala(@_) }
sub lala { oink(@_) }
sub oink { flarp(@_) }
sub flarp { zot(@_) }
sub zot { $_[0]->() }
cmpthese( -0.5, {
eval => 'local $@; eval { 1; }',
try => 'try { die "foo" } catch { /foo/ }',
die => 'local $@; eval { die "foo"; }',
die_ref => 'local $@; eval { die {}; }',
# a bit of perspective on the time scales
new => 'Empty->new',
throwable_new => 'Foo->new',
throwable_throw => 'local $@; eval { Foo->throw }',
new_hash => 'my %h = map { $_ => "foo" } 1 .. 100',
deep_die => 'local $@; eval { foo(sub { die "foo" }) }',
# stack introspection and string futzing
confess => 'local $@; eval { Carp::confess("foo") }',
deep_confess => 'local $@; eval { foo(sub { Carp::confess("foo") }); }',
croak => 'local $@; eval { Carp::croak("foo") }',
# stack introspection
shortmess => 'Carp::shortmess()',
longmess => 'Carp::longmess()',
stack_trace => 'Devel::StackTrace->new',
deep_stack_trace => 'foo(sub { Devel::StackTrace->new })',
# stock error objects from the CPAN
throwable_error => q{
local $@;
eval {
Throwable::Error->throw( message => "foo" );
};
},
exception_class => q{
local $@;
eval {
MyException->throw( error => "foo", foo => "bar" );
};
},
error_simple => 'local $@; eval { Error::Simple->throw("foo") }',
});
Rate deep_confess throwable_error confess longmess exception_class deep_stack_trace new_hash stack_trace croak shortmess error_simple throwable_throw try throwable_new deep_die new die die_ref eval
deep_confess 1147/s -- -44% -49% -59% -64% -79% -80% -90% -91% -92% -98% -98% -98% -99% -99% -100% -100% -100% -100%
throwable_error 2035/s 77% -- -10% -26% -36% -63% -65% -83% -84% -86% -97% -97% -97% -98% -99% -99% -100% -100% -100%
confess 2261/s 97% 11% -- -18% -28% -59% -61% -81% -82% -85% -96% -97% -97% -98% -99% -99% -100% -100% -100%
longmess 2765/s 141% 36% 22% -- -13% -50% -53% -76% -78% -81% -95% -96% -96% -97% -99% -99% -99% -100% -100%
exception_class 3162/s 176% 55% 40% 14% -- -43% -46% -73% -75% -79% -95% -96% -96% -97% -98% -99% -99% -100% -100%
deep_stack_trace 5530/s 382% 172% 145% 100% 75% -- -6% -53% -56% -63% -91% -92% -93% -94% -97% -98% -99% -100% -100%
new_hash 5856/s 411% 188% 159% 112% 85% 6% -- -50% -53% -60% -90% -92% -92% -94% -97% -98% -99% -100% -100%
stack_trace 11711/s 921% 475% 418% 324% 270% 112% 100% -- -6% -21% -80% -84% -84% -87% -94% -95% -98% -99% -100%
croak 12444/s 985% 512% 450% 350% 294% 125% 113% 6% -- -16% -79% -83% -83% -86% -94% -95% -98% -99% -99%
shortmess 14768/s 1188% 626% 553% 434% 367% 167% 152% 26% 19% -- -75% -80% -80% -84% -92% -94% -97% -99% -99%
error_simple 59077/s 5052% 2803% 2513% 2037% 1768% 968% 909% 404% 375% 300% -- -18% -20% -36% -70% -76% -88% -95% -97%
throwable_throw 72404/s 6214% 3458% 3102% 2519% 2190% 1209% 1136% 518% 482% 390% 23% -- -2% -21% -63% -71% -86% -94% -97%
try 73770/s 6333% 3525% 3163% 2568% 2233% 1234% 1160% 530% 493% 400% 25% 2% -- -20% -62% -70% -86% -94% -97%
throwable_new 91995/s 7923% 4421% 3969% 3227% 2809% 1564% 1471% 686% 639% 523% 56% 27% 25% -- -53% -63% -82% -92% -96%
deep_die 194606/s 16871% 9463% 8507% 6939% 6055% 3419% 3223% 1562% 1464% 1218% 229% 169% 164% 112% -- -22% -62% -84% -92%
new 249683/s 21675% 12169% 10942% 8931% 7796% 4415% 4164% 2032% 1906% 1591% 323% 245% 238% 171% 28% -- -51% -79% -89%
die 508969/s 44287% 24911% 22410% 18309% 15996% 9104% 8592% 4246% 3990% 3346% 762% 603% 590% 453% 162% 104% -- -57% -78%
die_ref 1194086/s 104035% 58577% 52710% 43089% 37664% 21494% 20292% 10096% 9495% 7986% 1921% 1549% 1519% 1198% 514% 378% 135% -- -49%
eval 2348372/s 204700% 115299% 103759% 84838% 74169% 42369% 40005% 19953% 18771% 15802% 3875% 3143% 3083% 2453% 1107% 841% 361% 97% --
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment