Last active
March 20, 2021 14:33
-
-
Save kraih/5551292 to your computer and use it in GitHub Desktop.
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
# | |
# 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.9.2 (MacBook Air) with Perl 5.18.2 and EV 4.17 (kqueue) | |
# | |
# 560.9MB 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 $daemon = Mojo::Server::Daemon->new( | |
silent => 1, | |
app => app, | |
inactivity_timeout => 300, | |
listen => ['http://127.0.0.1'] | |
)->start; | |
my $port | |
= $daemon->ioloop->acceptor($daemon->acceptors->[0])->handle->sockport; | |
# 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->(); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment