1#! /usr/local/bin/perl -w
2#
3# DES_PP benchmarking.
4# Copyright 2000, Guido Flohr <guido@imperia.net>
5
6use strict;
7use IO::File;
8use POSIX;
9use Crypt::DES_PP;
10use Benchmark;
11
12use constant SECONDS_PER_TEST => 10;
13use constant KEY => 'PurePerl';
14use constant PLAINTEXT => 'PerlPunk';
15use constant CIPHERTEXT => 'PunkPerl';
16
17sub alarm_handler ($);
18
19my $clocks;
20my $elapsed = 0;
21
22STDOUT->autoflush (1);
23
24print <<EOF;
251..1
26=== Benchmarking DES_PP module. ===
27To pace directly against XS (embedded C code) version run \`\`perl test-xs''
28in this directory.
29EOF
30
31print "checking prerequisites... ";
32eval {
33    eval 'use POSIX qw (_SC_CLK_TCK);
34              $clocks = sysconf (&POSIX::_SC_CLK_TCK)';
35    if ($@) {
36	eval 'use POSIX qw (CLK_TCK);
37                      $clocks = sysconf (&POSIX::CLK_TCK)';
38	if ($@) {
39	    eval 'use POSIX qw (TICKS_PER_SEC);
40                              $clocks = POSIX::TICKS_PER_SEC';
41	}
42	die "can't find out your kernel's heartbeat\n" if $@;
43    }
44
45    if (exists $SIG{ALRM}) {
46	# Check if the POSIX version of times(2) is available.
47	die "POSIX::times not available\n"
48	    unless exists $POSIX::{times};
49
50    } else {
51	die "no SIGALRM available\n";
52    }
53};
54
55if ($@) {
56    print <<EOF;
57tsk, tsk
58Please reformat your harddisk and install an operating system before you
59proceed.
60ok # Skipped: $@
61EOF
62
63    exit 0;
64}
65
66print "looks fine\n";
67
68$SIG{ALRM} = \&alarm_handler;
69
70my $starttime;
71my $count = 0;
72
73my $des;
74
75print "Initializing 8-byte keys for ", SECONDS_PER_TEST, " seconds... ";
76eval {
77    (undef, $starttime) = POSIX::times;
78
79    alarm SECONDS_PER_TEST;
80    while (1) { $des = Crypt::DES_PP->new (KEY); ++$count };
81};
82die if $@ and $@ ne "alarm\n";
83
84my $keys_per_sec = ($clocks * $count) / $elapsed;
85print "$keys_per_sec keys per second\n";
86
87# Benchmark encryption.
88print "Encrypting 8-byte blocks for ", SECONDS_PER_TEST, " seconds... ";
89$des = Crypt::DES_PP->new (KEY);
90$count = 0;
91
92eval {
93    (undef, $starttime) = POSIX::times;
94
95    alarm SECONDS_PER_TEST;
96    while (1) { $des->encrypt (PLAINTEXT); ++$count };
97};
98die if $@ and $@ ne "alarm\n";
99
100my $encrypts_per_sec = ($clocks * $count) / $elapsed;
101print "$encrypts_per_sec encryptions per second\n";
102
103# Benchmark encryption.
104print "Decrypting 8-byte blocks for ", SECONDS_PER_TEST, " seconds... ";
105$des = Crypt::DES_PP->new (KEY);
106$count = 0;
107
108eval {
109    (undef, $starttime) = POSIX::times;
110
111    alarm SECONDS_PER_TEST;
112    while (1) { $des->decrypt (CIPHERTEXT); ++$count };
113};
114die if $@ and $@ ne "alarm\n";
115
116my $decrypts_per_sec = ($clocks * $count) / $elapsed;
117print "$decrypts_per_sec decryptions per second\n";
118
119# Run in Cipher Block Chaining Mode.
120use constant EIGHT_BYTE_BLOCKS => 20_000;
121my $plaintext = PLAINTEXT x EIGHT_BYTE_BLOCKS;
122my ($start, $end);
123my $timediff = '';
124my $des_driver = 'DES';
125my $des_pp_driver = 'DES_PP';
126
127# First pure Perl version.
128print "Encrypting ", EIGHT_BYTE_BLOCKS << 3, " bytes in CBC mode...";
129eval '
130    use Crypt::CBC;
131
132    my $cipher = Crypt::CBC->new (KEY, $des_pp_driver);
133    my $start = Benchmark->new;
134    $cipher->encrypt ($plaintext);
135    my $end = Benchmark->new;
136    $timediff = timestr timediff $end, $start;
137';
138print $@ ? " skipped (Crypt::CBC not loadable)\n" :
139    " done\n$timediff\n";
140
141# Now the XS version.
142print "XS-Version: Encrypting ", EIGHT_BYTE_BLOCKS << 3,
143    " bytes bytes in CBC mode...";
144eval '
145    use Crypt::CBC;
146
147    my $cipher = Crypt::CBC->new (KEY, $des_driver);
148    my $start = Benchmark->new;
149    $cipher->encrypt ($plaintext);
150    my $end = Benchmark->new;
151    $timediff = timestr timediff $end, $start;
152';
153print $@ ? " skipped (Crypt::CBC or Crypt::DES not loadable)\n" :
154    " done\n$timediff\n";
155$timediff = 0;
156
157# Now with a non-cached key and 128 bytes of plaintext.
158$plaintext = PLAINTEXT x 16;
159print "Encrypting ", EIGHT_BYTE_BLOCKS,
160    " 128-byte-blocks in non-cached CBC mode...";
161eval '
162    use Crypt::CBC;
163
164    my $start = Benchmark->new;
165
166    for (1 .. EIGHT_BYTE_BLOCKS >> 3) {
167	my $cipher = Crypt::CBC->new (KEY, $des_pp_driver);
168	$cipher->encrypt ($plaintext);
169    }
170    my $end = Benchmark->new;
171    $timediff = timestr timediff $end, $start;
172';
173print $@ ? " skipped (Crypt::CBC not loadable)\n" :
174    " done\n$timediff\n";
175$timediff = 0;
176
177$plaintext = PLAINTEXT x 16;
178print "XS-Version: Encrypting ", EIGHT_BYTE_BLOCKS,
179    " 128-byte-blocks in non-cached CBC mode...";
180eval '
181    use Crypt::CBC;
182
183    my $start = Benchmark->new;
184
185    for (1 .. EIGHT_BYTE_BLOCKS >> 3) {
186	my $cipher = Crypt::CBC->new (KEY, $des_driver);
187	$cipher->encrypt ($plaintext);
188    }
189    my $end = Benchmark->new;
190    $timediff = timestr timediff $end, $start;
191';
192print $@ ? " skipped (Crypt::CBC not loadable)\n" :
193    " done\n$timediff\n";
194print "ok 1\n";
195
196sub alarm_handler ($) {
197    my (undef, $endtime) = POSIX::times;
198
199    $elapsed = $endtime - $starttime;
200
201    die "alarm\n";
202}
203
204
205
206
207