my %params = $r->args;
only the last value will be stored and the rest will collapse,
because that's what happens when you turn a list
into a hash. Assuming that you have the following list:
(rules => 'Apache', rules => 'Perl', rules => 'mod_perl')
and assign it to a hash, the following happens:
$hash{rules} = 'Apache';
$hash{rules} = 'Perl';
$hash{rules} = 'mod_perl';
So at the end only the following pair will get stored:
rules => 'mod_perl'
With CGI.pm or Apache::Request,
you can solve this by extracting the whole list by its key:
my @values = $q->param('rules');
In addition, Apache::Request and
CGI.pm have many more functions that ease input
processing, such as handling file uploads. However,
Apache::Request is theoretically much faster,
since its guts are implemented in C, glued to Perl using XS code.
use Apache::RegistryLoader ( );
use CGI ( );
CGI->compile('param');
use Apache::Request ( );
# Preload registry scripts
Apache::RegistryLoader->new->handler(
"/perl/processing_with_cgi_pm.pl",
"/home/httpd/perl/processing_with_cgi_pm.pl"
);
Apache::RegistryLoader->new->handler(
"/perl/processing_with_apache_request.pl",
"/home/httpd/perl/processing_with_apache_request.pl"
);
Apache::RegistryLoader->new->handler(
"/perl/processing_with_apache_args.pl",
"/home/httpd/perl/processing_with_apache_args.pl"
);
1;
We use four different query strings, generated by:
my @queries = (
join("&", map {"$_=" . 'e' x 10} ('a'..'b')),
join("&", map {"$_=" . 'e' x 50} ('a'..'b')),
join("&", map {"$_=" . 'e' x 5 } ('a'..'z')),
join("&", map {"$_=" . 'e' x 10} ('a'..'z')),
);
The first string is:
a=eeeeeeeeee&b=eeeeeeeeee
which is 25 characters in length and consists of two key/value pairs.
The second string is also made of two key/value pairs, but the values
are 50 characters long (a total of 105 characters). The third and
fourth strings are each made from 26 key/value pairs, with value
lengths of 5 and 10 characters respectively and total lengths of 207
and 337 characters respectively. The query_len
column in the report table is one of these four total lengths.
---------------------------------------------
name val_len pairs query_len | avtime rps
---------------------------------------------
apreq 10 2 25 | 51 945
apreq 50 2 105 | 53 907
r_args 50 2 105 | 53 906
r_args 10 2 25 | 53 899
apreq 5 26 207 | 64 754
apreq 10 26 337 | 65 742
r_args 5 26 207 | 73 665
r_args 10 26 337 | 74 657
cgi_pm 50 2 105 | 85 573
cgi_pm 10 2 25 | 87 559
cgi_pm 5 26 207 | 188 263
cgi_pm 10 26 337 | 188 262
---------------------------------------------
where apreqstands for
Apache::Request::param( ),
r_argsstands for Apache::args(
) or $r->args( ), and
cgi_pmstands for CGI::param(
).
You can see that Apache::Request::param and
Apache::args have similar performance with a few
key/value pairs, but the former is faster with many key/value pairs.
CGI::param is significantly slower than the other
two methods.
These results also suggest that the processing gets progressively
slower as the number of key/value pairs grows, but longer lengths of
the key/value pairs have less of a slowdown impact. To verify that,
let's use the
Apache::Request::param method and first test
several query strings made of five key/value pairs with value lengths
growing from 10 characters to 60 in steps of 10:
my @strings = map {'e' x (10*$_)} 1..6;
my @ae = ('a'..'e');
my @queries = ( );
for my $string (@strings) {
push @queries, join "&", map {"$_=$string"} @ae;
}
The results are:
-----------------------------------
val_len query_len | avtime rps
-----------------------------------
10 77 | 55 877
20 197 | 55 867
30 257 | 56 859
40 137 | 56 858
50 317 | 56 857
60 377 | 58 828
-----------------------------------
Indeed, the length of the value influences the speed very little, as
we can see that the average processing time almost
doesn't change as the length of the value grows.
Now let's use a fixed value length of 10 characters
and test with a varying number of key/value pairs, from 2 to 26 in
steps of 5:
my @az = ('a'..'z');
my @queries = map { join("&", map {"$_=" . 'e' x 10 } @az[0..$_]) }
(1, 5, 10, 15, 20, 25);
The results are:
-------------------------------
pairs query_len | avtime rps
-------------------------------
2 25 | 53 906
6 77 | 55 869
12 142 | 57 838
16 207 | 61 785
21 272 | 64 754
26 337 | 66 726
-------------------------------