#!/usr/bin/perl
# Originaly at:
# http://idisk.mac.com/christian.hansen/Public/perl/serialize.pl
# Updated by Peter Makholm, June 2009
# http://gist.github.com/130005
# - Added Data::Dumper and a current set of YAML/JSON modules
# - added tags for the -b option: :core, :yaml, :json
# see bottom of this script for benchmark results.
use strict;
use warnings;
use Benchmark qw[cmpthese timethis timestr];
use Getopt::Long qw[];
use UNIVERSAL::require qw[];
my $benchmarks = {
'Bencode' => {
deflate => sub { Bencode::bencode($_[0]) },
inflate => sub { Bencode::bdecode($_[0]) }
},
'Convert::Bencode' => {
deflate => sub { Convert::Bencode::bencode($_[0]) },
inflate => sub { Convert::Bencode::bdecode($_[0]) }
},
'Convert::Bencode_XS' => {
deflate => sub { Convert::Bencode_XS::bencode($_[0]) },
inflate => sub { Convert::Bencode_XS::bdecode($_[0]) }
},
'Data::Dumper' => {
deflate => sub { Data::Dumper->Dump([ $_[0] ]) },
inflate => sub { my $VAR1; eval $_[0] },
default => 1,
core => 1,
},
'Data::Taxi' => {
deflate => sub { Data::Taxi::freeze($_[0]) },
inflate => sub { Data::Taxi::thaw($_[0]) },
},
'FreezeThaw' => {
deflate => sub { FreezeThaw::freeze($_[0]) },
inflate => sub { FreezeThaw::thaw($_[0]) },
default => 1
},
'JSON::PP' => {
deflate => sub { JSON::PP::encode_json($_[0]) },
inflate => sub { JSON::PP::decode_json($_[0]) },
default => 1,
json => 1
},
'JSON::XS' => {
deflate => sub { JSON::XS::encode_json($_[0]) },
inflate => sub { JSON::XS::decode_json($_[0]) },
default => 1,
json => 1
},
'Storable' => {
deflate => sub { Storable::nfreeze($_[0]) },
inflate => sub { Storable::thaw($_[0]) },
default => 1,
core => 1,
},
'PHP::Serialization' => {
deflate => sub { PHP::Serialization::serialize($_[0]) },
inflate => sub { PHP::Serialization::unserialize($_[0]) }
},
'RPC::XML' => {
deflate => sub { RPC::XML::response->new($_[0]) },
inflate => sub { RPC::XML::Parser->new->parse($_[0]) },
packages => ['RPC::XML::Parser']
},
'YAML::Old' => {
deflate => sub { YAML::Old::Dump($_[0]) },
inflate => sub { YAML::Old::Load($_[0]) },
default => 1,
yaml => 1
},
'YAML::XS' => {
deflate => sub { YAML::XS::Dump($_[0]) },
inflate => sub { YAML::XS::Load($_[0]) },
default => 1,
yaml => 1
},
'YAML::Tiny' => {
deflate => sub { YAML::Tiny::Dump($_[0]) },
inflate => sub { YAML::Tiny::Load($_[0]) },
default => 1,
yaml => 1
},
'XML::Simple' => {
deflate => sub { XML::Simple::XMLout($_[0]) },
inflate => sub { XML::Simple::XMLin($_[0]) },
default => 1
}
};
my @benchmark = (); # package names of benchmarks to run
my $iterations = -1; # integer
my $benchmark_deflate = 1; # boolean
my $benchmark_inflate = 1; # boolean
my $output = 'chart'; # chart or time
my $width = 0;
my $results = { };
my $structure = {
array => [ 'a' .. 'j' ],
hash => { 'a' .. 'z' },
string => 'x' x 200
};
Getopt::Long::Configure( 'bundling' );
Getopt::Long::GetOptions(
'b|benchmark=s@' => sub {
if ( lc $_[1] eq 'all' ) {
return @benchmark = keys %{ $benchmarks };
}
if ( lc $_[1] eq 'default' ) {
return @benchmark = grep { $benchmarks->{ $_ }->{default} } keys %{ $benchmarks };
}
if ( $_[1] =~ /^:(.*)/ ) {
return @benchmark = grep { $benchmarks->{ $_ }->{$1} } keys %{ $benchmarks };
}
if ( exists $benchmarks->{ $_[1] } ) {
return push( @benchmark, $_[1] );
}
die "Unknown benchmark '$_[1]'.\n";
},
'deflate!' => \$benchmark_deflate,
'inflate!' => \$benchmark_inflate,
'i|iterations=i' => \$iterations,
'o|output=s' => \$output,
's|structure=s' => sub {
die "Structure option requires YAML.\n"
unless YAML->require;
$structure = YAML::LoadFile( $_[1] );
}
) or exit 1;
@benchmark = grep { $benchmarks->{ $_ }->{default} } keys %{ $benchmarks }
unless @benchmark;
$width = width(@benchmark);
print "\nModules\n";
BENCHMARK:
foreach my $package ( sort @benchmark ) {
my $benchmark = $benchmarks->{$package};
my @packages = ( $package, @{ $benchmark->{packages} || [] } );
$_->require or next BENCHMARK for @packages;
my $deflate = $benchmark->{deflate};
my $inflate = $benchmark->{inflate};
printf( "%-${width}s : %s\n", $package, $package->VERSION );
$results->{deflate}->{$package} = time_deflate( $deflate, $inflate )
if $benchmark_deflate;
$results->{inflate}->{$package} = time_inflate( $deflate, $inflate )
if $benchmark_inflate;
}
output( 'Deflate', $output, $results->{deflate} )
if $benchmark_deflate;
output( 'Inflate', $output, $results->{inflate} )
if $benchmark_inflate;
sub output {
my $title = shift;
my $output = shift;
printf( "\n%s\n", $title );
return ( $output eq 'time' ) ? &output_time : &output_chart;
}
sub output_chart {
my $results = shift;
cmpthese($results);
}
sub output_time {
my $results = shift;
foreach my $title ( sort keys %{ $results } ) {
printf( "%-${width}s %s\n", $title, timestr( $results->{ $title } ) );
}
}
sub time_deflate {
my ( $deflate, $inflate ) = @_;
return timethis( $iterations, sub { &$deflate($structure) }, '', 'none' );
}
sub time_inflate {
my ( $deflate, $inflate ) = @_;
my $deflated = &$deflate($structure);
return timethis( $iterations, sub { &$inflate($deflated) }, '', 'none' );
}
sub width {
return length( ( sort { length $a <=> length $b } @_ )[-1] );
}
__DATA__
Modules
Bencode : 1.31
Convert::Bencode : 1.03
Convert::Bencode_XS : 0.06
Data::Dumper : 2.121_14
Data::Taxi : 0.95
FreezeThaw : 0.45
JSON::PP : 2.24000
JSON::XS : 2.24
PHP::Serialization : 0.31
RPC::XML : 1.41
Storable : 2.20
XML::Simple : 2.18
YAML::Old : 0.81
YAML::Tiny : 1.39
YAML::XS : 0.32
Deflate
Rate YAML::Old Data::Taxi PHP::Serialization XML::Simple JSON::PP RPC::XML YAML::Tiny Bencode Data::Dumper Convert::Bencode FreezeThaw YAML::XS Storable Convert::Bencode_XS JSON::XS
YAML::Old 257/s -- -85% -89% -90% -91% -92% -94% -96% -97% -97% -97% -98% -99% -99% -100%
Data::Taxi 1737/s 577% -- -26% -35% -38% -47% -62% -76% -82% -82% -82% -86% -94% -96% -99%
PHP::Serialization 2353/s 817% 35% -- -12% -16% -28% -48% -67% -75% -75% -76% -82% -92% -95% -99%
XML::Simple 2668/s 940% 54% 13% -- -5% -18% -41% -63% -72% -72% -72% -79% -91% -94% -99%
JSON::PP 2815/s 997% 62% 20% 6% -- -14% -38% -61% -70% -71% -71% -78% -90% -94% -99%
RPC::XML 3272/s 1175% 88% 39% 23% 16% -- -28% -55% -65% -66% -66% -74% -89% -93% -98%
YAML::Tiny 4516/s 1660% 160% 92% 69% 60% 38% -- -38% -52% -53% -53% -65% -84% -90% -98%
Bencode 7226/s 2717% 316% 207% 171% 157% 121% 60% -- -23% -24% -25% -43% -75% -84% -96%
Data::Dumper 9402/s 3565% 441% 300% 252% 234% 187% 108% 30% -- -2% -3% -26% -68% -79% -95%
Convert::Bencode 9567/s 3629% 451% 307% 259% 240% 192% 112% 32% 2% -- -1% -25% -67% -78% -95%
FreezeThaw 9654/s 3663% 456% 310% 262% 243% 195% 114% 34% 3% 1% -- -24% -67% -78% -95%
YAML::XS 12752/s 4871% 634% 442% 378% 353% 290% 182% 76% 36% 33% 32% -- -56% -71% -94%
Storable 29119/s 11250% 1576% 1137% 992% 934% 790% 545% 303% 210% 204% 202% 128% -- -34% -86%
Convert::Bencode_XS 44126/s 17100% 2440% 1775% 1554% 1468% 1249% 877% 511% 369% 361% 357% 246% 52% -- -78%
JSON::XS 202569/s 78858% 11561% 8508% 7493% 7096% 6091% 4386% 2703% 2055% 2017% 1998% 1489% 596% 359% --
Inflate
Rate YAML::Old XML::Simple PHP::Serialization Data::Taxi JSON::PP YAML::Tiny Convert::Bencode FreezeThaw RPC::XML Bencode Data::Dumper YAML::XS Convert::Bencode_XS Storable JSON::XS
YAML::Old 190/s -- -45% -73% -79% -83% -90% -91% -93% -93% -95% -98% -99% -100% -100% -100%
XML::Simple 345/s 82% -- -50% -61% -68% -82% -84% -87% -88% -91% -97% -98% -99% -99% -100%
PHP::Serialization 692/s 265% 100% -- -23% -37% -63% -68% -73% -76% -81% -94% -95% -99% -99% -99%
Data::Taxi 894/s 371% 159% 29% -- -18% -52% -58% -66% -69% -76% -92% -94% -98% -99% -99%
JSON::PP 1093/s 476% 217% 58% 22% -- -42% -49% -58% -62% -70% -90% -93% -98% -98% -99%
YAML::Tiny 1876/s 889% 443% 171% 110% 72% -- -12% -28% -34% -49% -84% -87% -96% -97% -98%
Convert::Bencode 2129/s 1023% 516% 208% 138% 95% 14% -- -18% -26% -42% -81% -86% -96% -97% -98%
FreezeThaw 2597/s 1269% 652% 276% 191% 138% 38% 22% -- -9% -30% -77% -83% -95% -96% -97%
RPC::XML 2860/s 1408% 728% 314% 220% 162% 52% 34% 10% -- -22% -75% -81% -94% -95% -97%
Bencode 3688/s 1845% 968% 433% 313% 237% 97% 73% 42% 29% -- -68% -75% -93% -94% -96%
Data::Dumper 11387/s 5903% 3196% 1546% 1174% 941% 507% 435% 338% 298% 209% -- -24% -77% -82% -87%
YAML::XS 14975/s 7795% 4235% 2065% 1576% 1270% 698% 603% 477% 424% 306% 32% -- -70% -76% -83%
Convert::Bencode_XS 49227/s 25853% 14150% 7017% 5408% 4402% 2524% 2212% 1795% 1621% 1235% 332% 229% -- -21% -44%
Storable 62453/s 32825% 17978% 8930% 6888% 5612% 3229% 2833% 2305% 2084% 1593% 448% 317% 27% -- -29%
JSON::XS 88311/s 46458% 25464% 12668% 9781% 7976% 4607% 4047% 3300% 2988% 2294% 676% 490% 79% 41% --