public
Last active

  • Download Gist
c10k.pl
Perl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#
# Open 10k concurrent WebSocket connections with the client and server running
# in the same process and perform 10k WebSocket message roundtrips
#
# Tested on OS X 10.8.3 (MacBook Air) with Perl 5.16.3 and EV 4.15 (kqueue)
#
# 632.3MB memory usage, 0% CPU usage once roundtrips are finished after 36s
# (with all 20k sockets still open)
#
# Get the latest version of Mojolicious from http://github.com/kraih/mojo
# $ sudo sysctl -w kern.maxfiles=40960 kern.maxfilesperproc=20480
# $ ulimit -n 20480
# $ LIBEV_FLAGS=8 perl c10k.pl
#
use Mojo::Base -strict;
use Mojolicious::Lite;
use Mojo::IOLoop;
use Mojo::Server::Daemon;
use Mojo::UserAgent;
 
# Silence
app->log->level('error');
 
# Echo incoming WebSocket messages
my $num;
websocket '/' => sub {
my $self = shift;
say 'Opened: ', ++$num;
$self->on(message => sub { shift->send(shift) });
$self->on(finish => sub { say 'Closed: ', --$num });
};
 
# Server with longer than normal inactivity timeout
my $port = Mojo::IOLoop->generate_port;
my $daemon = Mojo::Server::Daemon->new(
silent => 1,
app => app,
inactivity_timeout => 300,
listen => ["http://*:$port"]
);
$daemon->start;
 
# Our event loop will have to handle 20k sockets
Mojo::IOLoop->singleton->max_connections(100000);
 
# Client with longer than normal connect and inactivity timeout
my $ua
= Mojo::UserAgent->new(connect_timeout => 300, inactivity_timeout => 300);
 
# 100 batches of 100 WebSocket connections
my $start = time;
my $timing = Mojo::IOLoop->delay(
sub { say '10k roundtrips finished in ', (time - $start), ' seconds.' });
_batch(100);
Mojo::IOLoop->start;
 
sub _batch {
return unless my $batch = shift;
say 'Batch: ', $batch--;
my $next = Mojo::IOLoop->delay(sub { _batch($batch) });
for (1 .. 100) {
my $connected = $next->begin;
my $received = $timing->begin;
$ua->websocket("ws://localhost:$port" => sub {
my ($ua, $tx) = @_;
say 'WebSocket handshake failed!' and return unless $tx->is_websocket;
$tx->on(message => $received);
$tx->send('Hello Mojo!');
$connected->();
});
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.