Benchmarking IMAP servers

There will be 4 tests against mailboxes of varying sizes; 100, 1000, and 10000 messages. Each of the tests will be repeated in full 5 times, and an average calculated.

Test #1: A stat of a fresh mailbox - at this point the mailbox will never have been accessed Test #2: A stat of the mailbox again Test #3: Accessing message 85 - a ‘random’ message Test #4: Flagging all messages as deleted, and then expunging them

The tests currently will be run against cyrus and courier imap servers. Configs are left as-is except what was required to change to get the mailboxes working with plain text login.

Hardware

The tests were run on a old p3 server, with a single IDE hard disk drive. The system is on a single partition (except / boot) which is formatted as EXT3.

# cat /proc/cpuinfo 
processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 8
model name      : Pentium III (Coppermine)
stepping        : 3
cpu MHz         : 802.043
cache size      : 256 KB
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 2
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 sep mtrr pge mca cmov pat pse36 mmx fxsr sse
bogomips        : 1581.05

Software

Distro: Gentoo 2005.1
Kernel: Linux p3 2.6.12-gentoo-r6 
net-mail/cyrus-imapd-2.2.12  -afs -drac -idled -kerberos +pam -snmp +ssl +tcpd
mail-mta/exim-4.50-r1  -X -dnsdb -exiscan -exiscan-acl -ipv6 -ldap +lmtp -mailwrapper -mbox -mysql -nis +pam +perl -postgres -sasl +ssl -syslog +tcpd
net-mail/courier-imap-4.0.1  +berkdb -debug -fam +gdbm -ipv6 +nls (-selinux)

Scripts used

Script used to create test data

Main test script: test.sh

#!/bin/sh

NUM_MAILS=10000
USER="cyrus"
PASS="password"

./emails.sh $NUM_MAILS $USER
./virgin.pl localhost $USER $PASS
./virgin.pl localhost $USER $PASS
./fetch.pl localhost $USER $PASS
./delete.pl localhost $USER $PASS $NUM_MAILS

email.sh

#!/bin/sh

n=0
while test $n -lt $1
do
    echo "this is a test mail!!!" | uuencode - | mail -s "Test message $n" $2

    n=`expr $n + 1`
done

./virgin.pl

#!/usr/bin/perl -w

use Expect;
use Time::HiRes qw(gettimeofday tv_interval);

die "Usage: $0 server user password\n" if $#ARGV != 2;

our $server=$ARGV[0];
our $user=$ARGV[1];
our $password=$ARGV[2];
our $ok = '^\d+\s+OK';

print "Testing select on $user\n";
my $exp = Expect->spawn("telnet", "$server", "143") or die "Could not connect"; 

$exp->expect(2, "-re", '^\* OK') or die "didn't see OK";
$exp->send("001 LOGIN $user $password\n");
$exp->expect(20, "-re", "$ok") or die "didn't see OK";

$t0 = [gettimeofday];
$exp->send("002 SELECT INBOX\n");
$exp->expect(30, "-re", "$ok") or die "didn't see OK";
$time = tv_interval($t0 , [gettimeofday]);

$exp->send("002 LOGOUT\n");
$exp->expect(5, "-re", "$ok") or die "didn't see OK";
$exp->hard_close();

open (LOGFILE, ">> output.log");
print LOGFILE "\nSelect INBOX Time: ", $time, " s\n";
close LOGFILE;

fetch.pl

#!/usr/bin/perl -w

# This test does a set of uid fetches

use Expect;
use Time::HiRes qw(gettimeofday tv_interval);

my @commands = (
 "SELECT INBOX",
 "FETCH 85 (FLAGS BODYSTRUCTURE)",
 "FETCH 85 BODY[HEADER]",
 "FETCH 85 BODY[1]"
 );

die "Usage: $0 server user password\n" if $#ARGV != 2;

our $server=$ARGV[0];
our $user=$ARGV[1];
our $password=$ARGV[2];
our $ok = '^\d+\s+OK';
our $num = 2;

my $exp = Expect->spawn("telnet", "$server", "143") or die "Could not connect"; 
$exp->expect(2, "-re", '^\* OK') or die "didn't see OK";
$exp->send("001 LOGIN $user $password\n");
$exp->expect(5, "-re", "$ok") or die "didn't see OK";

$t0 = [gettimeofday];
for $command (@commands) {
   $exp->send(sprintf("%03d %s\n", $num++, $command));
   $exp->expect(20, "-re", "$ok") or die "didn't see OK";
}
$time = tv_interval($t0 , [gettimeofday]);
$exp->send("999 LOGOUT\n");
$exp->expect(5, "-re", "$ok") or die "didn't see OK";
$exp->hard_close();

open (LOGFILE, ">> output.log");
print LOGFILE "\nFetch Mail 85 Time: ", $time, " s\n";
close LOGFILE;

delete.pl

#!/usr/bin/perl -w

# This test does a deletion of 10 messages, including the expunge

use Expect;
use Time::HiRes qw(gettimeofday tv_interval);


die "Usage: $0 server user password\n" if $#ARGV != 3;

our $server=$ARGV[0];
our $user=$ARGV[1];
our $password=$ARGV[2];
our $ok = '^\d+\s+OK';
our $num = 2;

my @commands = (
 'SELECT INBOX',
 'STORE 0:' . $ARGV[3] . ' +FLAGS (\Deleted)',
 'EXPUNGE',
 );

my $exp = Expect->spawn("telnet", "$server", "143") or die "Could not connect"; 
$exp->expect(5, "-re", '^\* OK') or die "didn't see OK";
$exp->send("001 LOGIN $user $password\n");
$exp->expect(5, "-re", "$ok") or die "didn't see OK";

$t0 = [gettimeofday];
for $command (@commands) {
   $exp->send(sprintf("%03d %s\n", $num++, $command));
   $exp->expect(600, "-re", "$ok") or die "didn't see OK";
}
$time = tv_interval($t0 , [gettimeofday]);
$exp->send("999 LOGOUT\n");
$exp->expect(5, "-re", "$ok") or die "didn't see OK";
$exp->hard_close();

open (LOGFILE, ">> output.log");
print LOGFILE "\nDelete All Mail Time: ", $time, " s\n";
close LOGFILE;

Exim Setup

begin routers

router_courier:
  driver = accept
  local_parts = courier
  transport = transport_courier
  
route_cyrus:
  driver = accept
  local_parts = cyrus
  transport = transport_cyrus

begin transports

transport_courier:
  driver = appendfile
  directory = /var/spool/mail/$local_part/Maildir
  maildir_format
  delivery_date_add
  envelope_to_add
  return_path_add
  group = mail
  mode = 0660

transport_cyrus:
     driver = pipe
     user = cyrus
     group = mail
     message_prefix = ""
     message_suffix = ""
     log_fail_output
     return_output
     envelope_to_add = true
     command = "/usr/lib/cyrus/deliver -r $return_path $local_part"

Setting up Courier

# userdb  courier set home=/var/spool/mail/courier/Maildir/ mail=/var/spool/mail/courier/Maildir/ uid=8 gid=12
# userdbpw -md5 | userdb courier set systempw
Password: 
Reenter password: 

Setting up Cyrus

# saslpasswd2 cyrus
Password:
# cyradm --user cyrus  localhost
Password: 
localhost> cm user.cyrus
#

Results

Cyrus with 100 emails

Pass #1 Pass #2 Pass #3 Pass #4 Pass #5 Avg.
Select INBOX Time 0.02079 s 0.026778 s 0.017001 s 0.01661 s 0.022283 s 0.0206924 s
Select INBOX Time 0.016981 s 0.016437 s 0.0174 s 0.016668 s 0.016487 s 0.0167946 s
Fetch Mail 85 Time: 0.027505 s 0.026558 s 0.02679 s 0.027753 s 0.027234 s 0.027168 s
Delete All Mail Time: 0.71607 s 0.712235 s 0.700168 s 0.628634 s 0.695603 s 0.690542 s

Cyrus with 1000 emails

Pass #1 Pass #2 Pass #3 Pass #4 Pass #5 Avg.
Select INBOX Time 0.017401 s 0.028108 s 0.018 s 0.018645 s 0.027476 s 0.021926 s
Select INBOX Time: 0.01735 s 0.016473 s 0.01748 s 0.016768 s 0.017668 s 0.0171478 s
Fetch Mail 85 Time: 0.02844 s 0.028391 s 0.028335 s 0.028039 s 0.029717 s 0.0285844 s
Delete All Mail Time: 6.357008 s 6.722728 s 6.547113 s 6.518259 s 6.26573 s 6.4821676 s

Cyrus with 10000 emails

Pass #1 Pass #2 Pass #3 Pass #4 Pass #5 Avg.
Select INBOX Time 0.02509 s 0.024013 s 0.024759 s 0.039652 s 0.044786 s 0.03166 s
Select INBOX Time: 0.023885 s 0.022277 s 0.023066 s 0.024021 s 0.023261 s 0.023302 s
Fetch Mail 85 Time: 0.034599 s 0.034738 s 0.034921 s 0.034499 s 0.03485 s 0.0347214 s
Delete All Mail Time: 63.572404 s 64.103166 s 64.885044 s 64.525608 s 64.575804 s 64.3324052 s

Courier with 100 emails

Pass #1 Pass #2 Pass #3 Pass #4 Pass #5 Avg.
Select INBOX Time 0.016494 s 0.016528 s 0.017743 s 0.019349 s 0.020325 s 0.0180878 s
Select INBOX Time 0.011814 s 0.011904 s 0.013547 s 0.014432 s 0.014947 s 0.0133288 s
Fetch Mail 85 Time: 0.100413 s 0.103036 s 0.102572 s 0.104415 s 0.104242 s 0.1029266 s
Delete All Mail Time: 0.100758 s 0.113163 s 0.111109 s 0.118635 s 0.131973 s 0.1151276 s

Courier with 1000 emails

Pass #1 Pass #2 Pass #3 Pass #4 Pass #5 Avg.
Select INBOX Time 0.286212 s 0.268349 s 0.318321 s 0.327233 s 0.338235 s 0.30167 s
Select INBOX Time 0.037391 s 0.046393 s 0.052735 s 0.062361 s 0.072064 s 0.0541888 s
Fetch Mail 85 Time: 0.128323 s 0.136582 s 0.139927 s 0.148851 s 0.15892 s 0.1425206 s
Delete All Mail Time: 1.150425 s 1.760016 s 2.458087 s 4.20293 s 6.827013 s 3.2376942 s

Courier with 10000 emails

Pass #1 Pass #2 Pass #3 Pass #4 Pass #5 Avg.
Select INBOX Time 43.05989 s 42.14172 s 41.156438 s 42.457034 s 40.053152 s 41.7736468 s
Select INBOX Time 0.303113 s 0.299262 s 0.299641 s 0.30249 s 0.304539 s 0.301809 s
Fetch Mail 85 Time: 0.386024 s 0.389193 s 0.389436 s 0.391477 s 0.392033 s 0.3896326 s
Delete All Mail Time: 131.052095 s 133.001318 s 131.905814 s 129.643691 s 128.014233 s 130.7234302 s

100 emails

Cyrus Courier Dovecot Diff.
Select INBOX Time 0.0206924 s 0.0180878 s
Select INBOX Time 0.0167946 s 0.0133288 s
Fetch Mail 85 Time: 0.027168 s 0.1029266 s
Delete All Mail Time: 0.690542 s 0.1151276 s

1000 emails

Cyrus Courier Dovecot Diff.
Select INBOX Time 0.021926 s 0.30167 s
Select INBOX Time 0.0171478 s 0.0541888 s
Fetch Mail 85 Time: 0.0285844 s 0.1425206 s
Delete All Mail Time: 6.4821676 s 3.2376942 s

10000 emails

Cyrus Courier Dovecot Diff.
Select INBOX Time 0.03166 s 41.7736468
Select INBOX Time 0.023302 s 0.301809 s
Fetch Mail 85 Time: 0.0347214 s 0.3896326 s
Delete All Mail Time: 64.3324052 s 130.7234302 s

—- References:

http://www.courier-mta.org/mbox-vs-maildir/

http://whizzo.uoregon.edu/public/src/mailperf/results.html