[jabberd] Jabber2 Stress Testing
Al Starbard
al at devianttechnologies.com
Sun Aug 8 14:17:38 CDT 2004
Hi Everyone,
We've been doing some stress testing of the j2 server and have some
results to share with the list. The server hardware is as follows:
- Two Intel Xeon 2.4GHz CPU with 512K cache, 533FSB
- 7GB DDR2100 (PC-266) ECC Registered DDR SDRAM
The test was structured to test message throughput and total
connections. We had enough client hardware to connect 6000 clients and
have them continuously sending messages to one another. The perl script
used for testing is attached. The settings are as follows:
- Karma disabled
- No message logging
- Unencrypted communications (5222)
- Message size: 140 chars
- Messages/User/Minute: 3
The results are:
Connections SM Size CPU C2S C2S Total
(MB) Load CPU % Size Msgs/Sec
(5 min) (MB)
500 15 0.02 10 25
1000 42 0.08 20 50
1500 85 0.2 40 75
2000 140 0.35 65 100
2500 214 0.3 70 125
3000 305 0.4 85 150
3500 431 0.45 90 175
4000 569 0.48 95 520 200
4500 713 0.66 98 540 225
5000 872 0.67 99 596 250
5500 1033 0.67 99 637 275
6000 1200 0.67 99 730 300
Some observations:
- The session manager proc grows continuously. If clients are
disconnected and reconnected the SM will grow further.
- The C2S proc continues to grow while under message traffic. Not sure
if this is due to a leak or C2S not being able to keep up with the
message traffic. It seemed to become CPU bound around 4500-5000 users
which is somewhere in the 225-250 msg/sec range. Not sure if this is
due to a leak or possibly messages being cached because c2s couldn't
keep up with the message traffic. Although, at 6000 users and 300
messages per second we tried sending messages to one another and found
there to be no noticable delay.
- The server appeared to be stable under load. It didn't crash until
the C2S finally got too large.
We plan some further tests in the near future. We'll send the results
to the list as get them.
--
Al Starbard
Deviant Technologies, Inc.
-------------- next part --------------
#!/usr/bin/perl -w
#===================================================================================
#
# FILE: bmark.pl
#
# USAGE: ./bmark.pl
#
# DESCRIPTION:
#
# FILES: ---
# NOTES: ---
# AUTHOR: <>
# COMPANY:
# VERSION: 1.0
# CREATED: 02/28/2004 03:42:10 PM EST
# REVISION: ---
# Usage message
my $USAGE = sub { my $scriptname = $0 =~ /[^\/]+$/ ? $& : $0; return
"\nUsage:\n\n"
. " $scriptname [-h]\n"
. " $scriptname users start\n"
. " -h : print this help message.\n"
. " -w window : time window (in seconds) for sending one message for each user pair.\n"
. " : default is 10 seconds.\n"
. " -l length : length of message to send.\n"
. " : default is 128 characters.\n"
. " users : number of users to connect.\n"
. " start : user number to begin with.\n"
. "\n";
};
#===================================================================================
use Benchmark;
use Time::HiRes qw(sleep);
use strict;
use Net::Jabber qw(Client);
use Getopt::Std;
# Setup signal handlers.
$SIG{INT} = sub { $main::done = 1; };
$SIG{TERM} = sub { $main::done = 1; };
# Get the command line options.
my ($opt_w, $opt_h, $opt_l);
my $opt_ok = getopts('hl:w:');
# Print the usage if -h or if there was an error
die &$USAGE if ((!$opt_ok || $opt_h) || @ARGV != 2);
my $users = shift;
die "Number of users must be a positive integer between 1 and 500.\n"
unless ($users >= 1 && $users <= 500);
my $start_user = shift;
die "Starting user must be a positive integer between 1 and 20000.\n"
unless ($start_user >= 1 && $start_user <= 20000);
$opt_w = 10 unless $opt_w;
$opt_l = 128 unless $opt_l;
our $done = 0;
our $caught_sig = 0;
my $server = "j2.devianttechnologies.com";
my $domain = "j2.devianttechnologies.com";
my $unames = "test";
my $padchars = $opt_l;
my $throttle = $opt_w;
my $port = "5222";
my $ssl = 0;
$port = "5223"
if( $ssl == 1 );
my $con_type = "tcpip";
$con_type = "http"
if( $ssl == 1 );
my $resource = "perl-jabber";
my $debuglevel = 0;
warn "Total message traffic is " . ($users/2)/$throttle . " $padchars character messages per second.\n";
warn "Equivalent to each user sending " . ($users/2)/$throttle*60/$users . " messages per minute.\n";
our $reciever_pid;
if( $reciever_pid = fork ) {
sender( $server, $port, $resource, $domain, $padchars, $throttle, $ssl, $con_type, $debuglevel, $users, $start_user );
} elsif( defined $reciever_pid ) {
reciever( $server, $port, $resource, $debuglevel, $ssl, $con_type);
}
sub reciever {
my $server = shift;
my $port = shift;
my $resource = shift;
my $debug = shift;
my $ssl = shift;
my $con_type = shift;
my @con;
my $i = $start_user + 1;
while( $i < ($users + $start_user) ) {
my $user = "test" . $i;
my $pass = "test" . $i;
my $con = jabber_connect( $server, $port, $user, $pass, $resource, $debug, $ssl, $con_type );
$con->SetMessageCallBacks(
normal=>\&handle_message,
chat=>\&handle_message
);
$con->RosterGet();
$con->PresenceSend();
$i += 2;
push(@con, $con);
}
# Keep processing events
while (1) {
foreach( @con ) {
print "Event did not process correctly!\n"
unless( defined($_->Process()) );
}
if ($done) {
warn "Receivier exiting.\n";
last;
}
}
foreach( @con ) {
$_->Disconnect();
}
}
sub sender {
my $server = shift;
my $port = shift;
my $resource = shift;
my $domain = shift;
my $padchars = shift;
my $throttle = shift;
my $ssl = shift;
my $con_type = shift;
my $debug = shift;
my $users = shift;
my $start_user = shift;
my $padding;
foreach( 1..$padchars ) {
$padding .= ".";
}
my @con;
my $i = $start_user;
while( $i < ($users + $start_user) ) {
my $user = "test" . $i;
my $pass = "test" . $i;
my $con = jabber_connect( $server, $port, $user, $pass, $resource, $debug, $ssl, $con_type );
$con->RosterGet();
$con->PresenceSend();
my $recipient = "test" . ($i + 1);
$con->{recipient} = $recipient . "\@" . $domain;
$i = $i + 2;
push(@con, $con);
}
my $delay = $throttle / @con;
while (1) {
my $t0 = new Benchmark;
foreach( @con ) {
my $timestamp = time();
my $mess = new Net::Jabber::Message();
$mess->SetMessage(
to=>$_->{recipient},
type=>"chat",
body=>"$padding :$timestamp"
);
$_->Send($mess);
sleep($delay);
}
my $t1 = new Benchmark;
#warn "Sent " . scalar(@con) . " messages in " . timestr(timediff($t1, $t0)) . "\n";
if ($done) {
warn "Sender exiting.\n";
last;
}
}
my $mess = new Net::Jabber::Message();
$mess->SetMessage(
to=>$_->{recipient},
type=>"chat",
body=>"DONE!"
);
$con[0]->Send($mess);
sleep(10);
foreach( @con ) {
$_->Disconnect();
}
}
sub jabber_connect {
my $con_server = shift;
my $con_port = shift;
my $con_user = shift;
my $con_password = shift;
my $con_resource = shift;
my $debug = shift;
my $ssl = shift;
my $con_type = shift;
my $ReCon = new Net::Jabber::Client(debuglevel=>$debug);
my @result = ();
$result[0] = "not ok";
while( $result[0] ne "ok" ) {
while( !($ReCon->Connected()) ) {
$ReCon->Connect(
hostname => $con_server,
port => $con_port,
connectiontype => $con_type,
ssl => $ssl,
);
}
@result = $ReCon->AuthSend (
username=>$con_user,
password=>$con_password,
resource=>$con_resource,
timeout => 60,
);
$result[0] = "not ok"
unless $result[0];
}
return $ReCon;
}
sub handle_message {
shift;
my $message = new Net::Jabber::Message(@_);
my $type = $message->GetType();
my $recieved_msg = $message->GetBody();
if( $recieved_msg eq 'DONE!' ) {
$done = 1;
return;
}
if( $type eq "chat" ) {
my $user_from = $message->GetFrom();
my( $bulk, $timestamp ) = split( /:/, $recieved_msg );
my $timelapse = time() - $timestamp;
my( $uname,$crap ) = split( /\@/, $user_from );
#print "message from $user_from - $timelapse secs\n";
}
}
More information about the jabberd
mailing list