Created
May 14, 2016 21:00
-
-
Save bokutin/5a5deb2eef789691267d979b83433f07 to your computer and use it in GitHub Desktop.
DBIx::Class and sereal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
use rlib; | |
use MyApp::Container qw(container); | |
use Modern::Perl; | |
use Sereal qw(encode_sereal); | |
my $id = 1234; | |
my $rs1 = container('schema')->resultset('Item')->search( | |
undef, | |
{ | |
prefetch => [ | |
'too_many_rels', | |
], | |
} | |
); | |
my $rs2 = container('schema')->resultset('Item')->search( | |
undef, | |
{ | |
prefetch => [ | |
'too_many_rels', | |
], | |
} | |
)->hashref_rs; | |
{ | |
no strict 'refs'; | |
*DBIx::Class::ResultSet::FREEZE = sub { | |
my ($self, $serializer) = @_; | |
my $to_serialize = { %$self }; | |
# A cursor in progress can't be serialized (and would make little sense anyway) | |
# the parser can be regenerated (and can't be serialized) | |
delete @{$to_serialize}{qw/cursor _row_parser _result_inflator/}; | |
# nor is it sensical to store a not-yet-fired-count pager | |
if ($to_serialize->{pager} and ref $to_serialize->{pager}{total_entries} eq 'CODE') { | |
delete $to_serialize->{pager}; | |
} | |
$to_serialize; | |
}; | |
*DBIx::Class::ResultSet::THAW = sub { | |
my ($class, $serializer, $data) = @_; | |
bless $data, $class; | |
}; | |
*DBIx::Class::ResultSource::FREEZE = sub { | |
$_[0]->handle; | |
}; | |
*DBIx::Class::ResultSource::THAW = sub { | |
my ($class, $serializer, $self) = @_; | |
$self->resolve; | |
}; | |
*DBIx::Class::ResultSourceHandle::FREEZE = sub { | |
my ($self, $serializer) = @_; | |
my $to_serialize = { %$self }; | |
delete $to_serialize->{schema}; | |
delete $to_serialize->{_detached_source}; | |
$to_serialize->{_frozen_from_class} = $self->{schema} | |
? $self->{schema}->class($self->source_moniker) | |
: $self->{_detached_source}->result_class | |
; | |
$to_serialize; | |
}; | |
*DBIx::Class::ResultSourceHandle::THAW = sub { | |
my ($class, $serializer, $data) = @_; | |
my $self = bless $data, $class; | |
my $thaw_schema = container('schema'); | |
my $from_class = delete $self->{_frozen_from_class}; | |
if( $thaw_schema ) { | |
$self->schema( $thaw_schema ); | |
} | |
elsif( my $rs = $from_class->result_source_instance ) { | |
# in the off-chance we are using CDBI-compat and have leaked $schema already | |
if( my $s = dbic_internal_try { $rs->schema } ) { | |
$self->schema( $s ); | |
} | |
else { | |
$rs->source_name( $self->source_moniker ); | |
$rs->{_detached_thaw} = 1; | |
$self->_detached_source( $rs ); | |
} | |
} | |
else { | |
DBIx::Class::Exception->throw( | |
"Thaw failed - original result class '$from_class' does not exist on this system" | |
); | |
} | |
$self; | |
}; | |
} | |
my $encoder = Sereal::Encoder->new( { freeze_callbacks => 1 } ); | |
my $decoder = Sereal::Decoder->new(); | |
my $obj = $rs1->find($id) or die; | |
my $hashref = $rs2->find($id) or die; | |
# { | |
# my $schema = container('schema'); | |
# my $obj = $schema->thaw($schema->freeze($obj)); | |
# } | |
# | |
# { | |
# my $obj = $decoder->decode($encoder->encode($obj)); | |
# } | |
use Benchmark qw(:all :hireswallclock); | |
use Storable qw(nfreeze); | |
my $schema = container('schema'); | |
my $count = 3000; | |
cmpthese($count, { | |
fetch_obj => sub { | |
$rs1->find($id) or die; | |
}, | |
fetch_hashref => sub { | |
$rs2->find($id) or die; | |
}, | |
storable_obj => sub { | |
$schema->freeze($obj); | |
}, | |
sereal_obj => sub { | |
$encoder->encode($obj); | |
}, | |
storable_hashref => sub { | |
nfreeze($hashref); | |
}, | |
sereal_hashref => sub { | |
encode_sereal($hashref); | |
}, | |
}); | |
__END__ | |
Rate fetch_obj fetch_hashref storable_obj sereal_obj storable_hashref sereal_hashref | |
fetch_obj 40.3/s -- -7% -97% -100% -100% -100% | |
fetch_hashref 43.2/s 7% -- -97% -99% -100% -100% | |
storable_obj 1444/s 3486% 3245% -- -82% -97% -98% | |
sereal_obj 8170/s 20198% 18832% 466% -- -85% -87% | |
storable_hashref 54857/s 136186% 127014% 3700% 571% -- -14% | |
sereal_hashref 64000/s 158900% 148200% 4333% 683% 17% -- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment