Skip to content

Instantly share code, notes, and snippets.

@ken39arg
Created November 26, 2013 15:20
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 ken39arg/7660216 to your computer and use it in GitHub Desktop.
Save ken39arg/7660216 to your computer and use it in GitHub Desktop.
multipartでデータを送るのと受け取るの
var express = require('express')
, fs = require('fs');
var app = module.exports = express.createServer();
app.configure(function(){
app.use( express.logger(':remote-addr - - [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"') );
app.use( express.bodyParser( {
maxFieldsSize : 10 * 1024 * 1024, // 10 MB
encoding: 'binary'
}));
app.use( app.router );
});
app.post('/', function(req, res) {
var data = req.body.data ? new Buffer( req.body.data, 'binary' )
: fs.readFileSync( req.files.data.path );
res.header('Content-Type', 'text/plain' );
res.header('Content-Length', data.length );
res.end( data );
} );
app.listen(3000);
#!/usr/bin/env perl
use strict;
use warnings;
use Plack::Request;
sub {
my $env = shift;
my $req = Plack::Request->new($env);
my $data = $req->param('data')|| do {
my $upload = $req->upload( 'data' );
open my $fh, '<', $upload->tempname;
my $buf = do { local $/; <$fh> };
close $fh;
$buf;
};
return [
"200",
["Content-Type" => "text/plain"],
[ $data ]
];
};
use common::sense;
use Benchmark qw/timethese cmpthese/ ;
use HTTP::Request::Common;
use LWP::UserAgent;
use bytes();
my $ua = LWP::UserAgent->new;
my $buffer;
{
open my $fh, '<', 'path/to/file/16MB';
$buffer = do { local $/; <$fh> };
close $fh;
}
sub echo_test {
my ($port, $buffer, $is_binary) = @_;
my $receive = '';
my $size = bytes::length $buffer;
my $length = 1024 * 1024 * 5;
for ( my $offset = 0; $offset < $size; $offset += $length ) {
my $send_bytes = bytes::substr( $buffer, $offset, $length );
my $data = ( $is_binary ) ? $send_bytes
: [ undef, 'data',
'Content-Type' => 'application/octet-stream',
'Content' => $send_bytes ];
my $res = $ua->request(POST "http://127.0.0.1:$port/", Content_Type => 'form-data',
Content => [ title => 'test', data => $data, ]);
$receive .= $res->content;
}
return $receive eq $buffer;
}
my $result = timethese( 20, {
'perl/binary' => sub {
my $status = echo_test( 5000, $buffer, 1 );
warn "Failed perl/binary" unless $status;
},
'perl/file' => sub {
my $status = echo_test( 5000, $buffer, 0 );
warn "Failed perl/file" unless $status;
},
'node/binary' => sub {
my $status = echo_test( 3000, $buffer, 1 );
warn "Failed node/binary" unless $status;
},
'node/file' => sub {
my $status = echo_test( 3000, $buffer, 0 );
warn "Failed node/file" unless $status;
},
});
cmpthese $result;
__END__
Benchmark: timing 20 iterations of node/binary, node/file, perl/binary, perl/file...
node/binary: 10 wallclock secs ( 4.30 usr + 1.72 sys = 6.02 CPU) @ 3.32/s (n=20)
node/file: 14 wallclock secs ( 5.50 usr + 2.68 sys = 8.18 CPU) @ 2.44/s (n=20)
perl/binary: 10 wallclock secs ( 4.35 usr + 1.76 sys = 6.11 CPU) @ 3.27/s (n=20)
perl/file: 13 wallclock secs ( 5.49 usr + 2.61 sys = 8.10 CPU) @ 2.47/s (n=20)
Rate node/file perl/file perl/binary node/binary
node/file 2.44/s -- -1% -25% -26%
perl/file 2.47/s 1% -- -25% -26%
perl/binary 3.27/s 34% 33% -- -1%
node/binary 3.32/s 36% 35% 1% --
@ken39arg
Copy link
Author

multipartでバイナリを送って受け取ろうとしたら思った以上に苦戦した。

  • node.js(express)では、bodyParserのオプションに {encoding: 'binary'} を指定して結果をBufferに入れないと壊れる
  • HTTP::Request::Commonでバイナリをファイルとして送るには Contentを $param = [ undef, $filename, Content => $buffer ] とする

試しにfileとbinaryどっちが良いのかベンチとって見たけど、当たり前だけどbinaryの方が良いよねって事だった。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment