7439 Mailmap for master
[koha.git] / misc / load_testing / benchmark_circulation.pl
1 #!/usr/bin/perl
2 # This script implements a basic benchmarking and regression testing
3 # utility for Koha
4
5 use strict;
6 use warnings;
7 BEGIN {
8     # find Koha's Perl modules
9     # test carefully before changing this
10     use FindBin;
11     eval { require "$FindBin::Bin/kohalib.pl" };
12 }
13
14 use HTTPD::Bench::ApacheBench;
15 use LWP::UserAgent;
16 use Data::Dumper;
17 use HTTP::Cookies;
18 use C4::Context;
19
20 my $baseurl= C4::Context->preference("staffClientBaseURL")."/cgi-bin/koha/";
21 my $max_tries = 200;
22 my $concurrency = 10;
23 my $debug;
24 my $user = 'kados';
25 my $password = 'kados';
26
27 # Authenticate via our handy dandy RESTful services
28 # and grab a cookie
29 my $ua = LWP::UserAgent->new();
30 my $cookie_jar = HTTP::Cookies->new();
31 my $cookie;
32 $ua->cookie_jar($cookie_jar);
33 my $resp = $ua->post( "$baseurl"."/svc/authentication" , {userid =>$user, password => $password} );
34 if( $resp->is_success ) {
35     $cookie_jar->extract_cookies( $resp );
36     $cookie = $cookie_jar->as_string;
37     print "Authentication successful\n";
38     print "Auth:\n $resp->content" if $debug;
39 }
40 # remove some unnecessary garbage from the cookie
41 $cookie =~ s/ path_spec; discard; version=0//;
42 $cookie =~ s/Set-Cookie3: //;
43
44 # Get some data to work with
45 my $dbh=C4::Context->dbh();
46 my $sth = $dbh->prepare("select max(borrowernumber) from borrowers");
47 $sth->execute;
48 my ($borrowernumber_max) = $sth->fetchrow;
49
50 $sth = $dbh->prepare("select max(biblionumber) from biblio");
51 $sth->execute;
52 my ($biblionumber_max) = $sth->fetchrow;
53
54 $sth = $dbh->prepare("select max(itemnumber) from items");
55 $sth->execute;
56 my ($itemnumber_max) = $sth->fetchrow;
57
58 $|=1;
59 #
60 # the global benchmark we do at the end...
61 #
62 my $b = HTTPD::Bench::ApacheBench->new;
63 $b->concurrency( $concurrency );
64 #
65 # mainpage : (very) low RDBMS dependency
66 #
67 my $b0 = HTTPD::Bench::ApacheBench->new;
68 $b0->concurrency( $concurrency );
69
70 my @mainpage;
71 print "--------------\n";
72 print "Koha circulation benchmarking utility\n";
73 print "--------------\n";
74 print "Benchmarking with $max_tries occurences of each operation and $concurrency concurrent sessions \n";
75 print "Load testing staff client dashboard page";
76 for (my $i=1;$i<=$max_tries;$i++) {
77     push @mainpage,"$baseurl/mainpage.pl";
78 }
79 my $run0 = HTTPD::Bench::ApacheBench::Run->new
80     ({ urls => \@mainpage,
81        cookies => [$cookie],
82     });
83 $b0->add_run($run0);
84 $b->add_run($run0);
85
86 # send HTTP request sequences to server and time responses
87 my $ro = $b0->execute;
88 # calculate hits/sec
89 print ("\t".$b0->total_time."ms\t".(1000*$b0->total_requests/$b0->total_time)." pages/sec\n");
90 print "ALERT : ".$b0->total_responses_failed." failures\n" if $b0->total_responses_failed;
91
92 #
93 # biblios
94 #
95 my $b1 = HTTPD::Bench::ApacheBench->new;
96 $b1->concurrency( $concurrency );
97
98 my @biblios;
99 print "Load testing catalog detail page";
100 for (my $i=1;$i<=$max_tries;$i++) {
101     my $rand_biblionumber = int(rand($biblionumber_max)+1);
102     push @biblios,"$baseurl/catalogue/detail.pl?biblionumber=$rand_biblionumber";
103 }
104 my $run1 = HTTPD::Bench::ApacheBench::Run->new
105     ({ urls => \@biblios,
106     });
107 $b1->add_run($run1);
108 $b->add_run($run1);
109
110 # send HTTP request sequences to server and time responses
111 $ro = $b1->execute;
112 # calculate hits/sec
113 print ("\t".$b1->total_time."ms\t".(1000*$b1->total_requests/$b1->total_time)." biblios/sec\n");
114 print "ALERT : ".$b1->total_responses_failed." failures\n" if $b1->total_responses_failed;
115
116 #
117 # borrowers
118 #
119 my $b2 = HTTPD::Bench::ApacheBench->new;
120 $b2->concurrency( $concurrency );
121
122 my @borrowers;
123 print "Load testing patron detail page";
124 for (my $i=1;$i<=$max_tries;$i++) {
125     my $rand_borrowernumber = int(rand($borrowernumber_max)+1);
126 #     print "$baseurl/members/moremember.pl?borrowernumber=$rand_borrowernumber\n";
127     push @borrowers,"$baseurl/members/moremember.pl?borrowernumber=$rand_borrowernumber";
128 }
129 my $run2 = HTTPD::Bench::ApacheBench::Run->new
130     ({ urls => \@borrowers,
131        cookies => [$cookie],
132     });
133 $b2->add_run($run2);
134 $b->add_run($run2);
135
136 # send HTTP request sequences to server and time responses
137 $ro = $b2->execute;
138 # calculate hits/sec
139 print ("\t".$b2->total_time."ms\t".(1000*$b2->total_requests/$b2->total_time)." borrowers/sec\n");
140
141
142 #
143 # issue (& then return) books
144 #
145 my $b3 = HTTPD::Bench::ApacheBench->new;
146 $b3->concurrency( $concurrency );
147 my $b4 = HTTPD::Bench::ApacheBench->new;
148 $b4->concurrency( $concurrency );
149
150 my @issues;
151 my @returns;
152 print "Load testing circulation transaction (checkouts)";
153 $sth = $dbh->prepare("SELECT barcode FROM items WHERE itemnumber=?");
154 my $sth2 = $dbh->prepare("SELECT borrowernumber FROM borrowers WHERE borrowernumber=?");
155 for (my $i=1;$i<=$max_tries;$i++) {
156     my $rand_borrowernumber;
157     # check that the borrowernumber exist
158     until ($rand_borrowernumber) {
159         $rand_borrowernumber = int(rand($borrowernumber_max)+1);
160         $sth2->execute($rand_borrowernumber);
161         ($rand_borrowernumber) = $sth2->fetchrow;
162     }
163     # find a barcode & check it exists
164     my $rand_barcode;
165     until ($rand_barcode) {
166         my $rand_itemnumber = int(rand($itemnumber_max)+1);
167         $sth->execute($rand_itemnumber);
168         ($rand_barcode) = $sth->fetchrow();
169     }
170     print "borrowernumber=$rand_borrowernumber&barcode=$rand_barcode\n";
171     push @issues,"$baseurl/circ/circulation.pl?borrowernumber=$rand_borrowernumber&barcode=$rand_barcode&issueconfirmed=1";
172     push @returns,"$baseurl/circ/returns.pl?barcode=$rand_barcode";
173 }
174 my $run3 = HTTPD::Bench::ApacheBench::Run->new
175     ({ urls => \@issues,
176        cookies => [$cookie],
177     });
178 $b3->add_run($run3);
179 $b->add_run($run3);
180
181 # send HTTP request sequences to server and time responses
182 $ro = $b3->execute;
183 # calculate hits/sec
184 print ("\t".$b3->total_time."ms\t".(1000*$b3->total_requests/$b3->total_time)." checkouts/sec\n");
185
186 print "Load testing circulation transaction (checkins)";
187 my $run4 = HTTPD::Bench::ApacheBench::Run->new
188     ({ urls => \@returns,
189        cookies => [$cookie],
190     });
191 $b4->add_run($run4);
192 $b->add_run($run4);
193
194 # send HTTP request sequences to server and time responses
195 $ro = $b4->execute;
196 # calculate hits/sec
197 print ("\t".$b4->total_time."ms\t".(1000*$b4->total_requests/$b4->total_time)." checkins/sec\n");
198
199 print "Load testing all transactions at once";
200 $ro = $b->execute;
201 print ("\t".$b->total_time."ms\t".(1000*$b->total_requests/$b->total_time)." operations/sec\n");