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