use strict;
use warnings;
use local::lib 'extlib';
use Benchmark ':all';
use Plack::Request;
use Plack::Builder;
# -------------------------------------------------------------------------
# RPC::XML
use RPC::XML;
use RPC::XML::ParserFactory;
my %dispatch_table = (
'MyRPC.sum' => sub {
return RPC::XML::response->new(0 + $_[0]->value + $_[1]->value);
},
);
my $parser = RPC::XML::ParserFactory->new(class => 'XML::LibXML');
my $rpc_xml_app = sub {
my $req = Plack::Request->new(@_);
my $q = $parser->parse($req->content);
my $method_name = $q->name;
my $code = $dispatch_table{$method_name} or return [404, [], ["not found: $method_name"]];
my $rpc_res = $code->(@{$q->args});
return [ 200, [ 'Content-Type', 'text/xml' ], [ $rpc_res->as_string ] ];
};
# -------------------------------------------------------------------------
# RPC::XML::Server::PSGI
use RPC::XML::Server::PSGI;
my $rpc_xml_server_psgi_app = do {
my $server = RPC::XML::Server::PSGI->new();
$server->add_proc(
{
name => 'MyRPC.sum',
code => sub {
return 0 + $_[0] + $_[1];
},
signature => ['string int int'],
}
);
$server->to_app();
};
# -------------------------------------------------------------------------
# XMLRPC::Lite
use XMLRPC::Lite;
use XMLRPC::Transport::HTTP::PSGI;
{
package MyRPC;
sub sum {
my ($class, $arg1, $arg2) = @_;
return $arg1 + $arg2;
}
}
my $xmlrpc_lite_app = XMLRPC::Transport::HTTP::PSGI->dispatch_to("MyRPC")->handle;
# -------------------------------------------------------------------------
# XML::RPC
use XML::RPC;
my %xmlrpc_dispatch_table = (
'MyRPC.sum' => sub {
return 0+$_[0]+$_[1];
},
);
my $xmlrpc = XML::RPC->new();
my $xml_rpc_app = sub {
my $req = Plack::Request->new(@_);
my $xml = $xmlrpc->receive($req->content, sub {
my $method_name = shift;
$xmlrpc_dispatch_table{$method_name}->(@_);
});
return [ 200, [ 'Content-Type', 'text/xml' ], [ $xml ] ];
};
# -------------------------------------------------------------------------
# XML::RPC::Fast
use XML::RPC::Fast;
use XML::RPC::Enc::LibXML;
my $xml_rpc_fast = XML::RPC::Fast->new(undef, encoder => XML::RPC::Enc::LibXML->new);
my $xml_rpc_fast_app = sub {
my $req = Plack::Request->new(@_);
my $xml = $xml_rpc_fast->receive($req->content, sub {
my $method_name = shift;
$xmlrpc_dispatch_table{$method_name}->(@_);
});
return [ 200, [ 'Content-Type', 'text/xml' ], [ $xml ] ];
};
# -------------------------------------------------------------------------
# RESTful JSON
use JSON::XS qw/encode_json/;
my %rest_dispatch_table = (
'/sum' => sub {
return 0+$_[0]->param('a')+$_[0]->param('b');
},
);
my $json_xs_app = sub {
my $req = Plack::Request->new(@_);
my $code = $rest_dispatch_table{$req->path_info} or return [404, [], []];
my $json = encode_json(+{result => scalar($code->($req))});
return [200, ['Content-Type', 'text/json'], [$json]];
};
# -------------------------------------------------------------------------
# benchmark
use HTTP::Request;
use HTTP::Message::PSGI;
my $rpc_req = RPC::XML::request->new( 'MyRPC.sum', 18, 22 );
my $rpc_content = $rpc_req->as_string;
my $req = HTTP::Request->new(
POST => 'http://localhost/',
[
'Content-Length' => length($rpc_content),
'Content-Type' => 'text/xml'
],
$rpc_content
);
my $rest_req = HTTP::Request->new(POST => 'http://localhost/sum?a=18&b=22');
print "RPC::XML: $RPC::XML::VERSION\n";
print "XMLRPC::Lite: $XMLRPC::Lite::VERSION\n";
print "XML::RPC: $XML::RPC::VERSION\n";
print "XML::RPC::Fast: $XML::RPC::VERSION\n";
print "-"x60, $/;
print $xmlrpc_lite_app->($req->to_psgi)->[2]->[0], $/;
print $xml_rpc_app->($req->to_psgi)->[2]->[0], $/;
print $rpc_xml_app->($req->to_psgi)->[2]->[0], $/;
print $xml_rpc_fast_app->($req->to_psgi)->[2]->[0], $/;
print $rpc_xml_server_psgi_app->($req->to_psgi)->[2]->[0], $/ for 1..10;
print "-"x60, $/;
my $x = timethese(
5000, {
# 'XMLRPC::Lite' => sub {
# $xmlrpc_lite_app->($req->to_psgi);
# },
'RPC::XML' => sub {
$rpc_xml_app->($req->to_psgi);
},
# 'RPC::XML::S::PSGI' => sub {
# $rpc_xml_server_psgi_app->($req->to_psgi);
# },
# 'XML::RPC' => sub {
# $xml_rpc_app->($req->to_psgi);
# },
'XML::RPC::Fast' => sub {
$xml_rpc_fast_app->($req->to_psgi);
},
# 'rest json' => sub {
# $json_xs_app->($rest_req->to_psgi);
# },
},
);
cmpthese($x);