I guess everyone here knows what merlyn thinks about
PHP: "Training wheels without the bike". This is easy to say
for someone like him, but in fact PHP is really popular, and
there must be a reason for this.
Today I took some benchmarks to see how PHP compares against
mod_perl, and the results are quite interesting. (I probably
wouldn't have posted them here, but some folks on the
chatterbox demanded them.)
I have two scripts, that do the same thing: they
connect to a MySQL address database and show a list of
entries. They produce the same output. One is written in PHP,
the other one is written in Perl, using CGI.pm and running as
an Apache::Registry script under mod_perl.
The benchmarking tool I used is "ab", the Apache Benchmark
that comes with the Apache distribution. I didn't tune the
server at all, leaving default entries for configuration
details like MinSpareServers (5), MaxSpareServers (10),
StartServers (5), MaxClients (150), MaxRequestsPerChild (0).
I simulated 10 users, where each user will make 10 requests,
so we have a total of 100 requests. Each script was tested
several runs, and these are the average numbers of
requests per second that Apache could handle:
|
Requests per second |
Perl script under Apache::Registry
(using CGI.pm) |
29 |
PHP script |
53! |
This was quite a shock to me. It means that the PHP script
is almost twice as fast than the Perl script! Where has the
famous performance of mod_perl gone?
I didn't want to believe this, so I hacked a third script,
all in all a copy of the Perl script, only different in
that I didn't use CGI.pm this time, but vanilla Apache
methods for parameter handling, headers setup and so on.
The results look like this:
|
Requests per second |
Perl script under Apache::Registry
(using CGI.pm) |
29 |
PHP script |
53 |
Apache::Registry script,
without CGI.pm |
60! |
Wow, this is a big performance gain, isn't it? Almost the
same script, but without CGI.pm. I'm curious if it can get
faster when I make it a real content handler instead of an
Apache::Registry script, but I didn't have the time for
that.
Used hard- and software:
AMD K6 400MHz,
128 MB RAM
FreeBSD 4.1-STABLE
Apache 1.3.12
mod_perl 1.24
mod_php 4.0.2
DBI 1.14
Mysql-Modules 1.2214
Training wheels, part II (was: RE: Training wheels again)
by le (Friar) on Sep 04, 2000 at 23:40 UTC
|
Just for the record:
Today I repeated my benchmark, adding another competitor,
a "real" PerlHandler script. (I simply took the 'clean'
Apache::Registry script and wrapped it inside a proper
Apache handler() sub.) These are the results:
|
Requests per second |
Perl script under Apache::Registry
(using CGI.pm) |
30 |
PHP script |
55 |
Apache::Registry script,
without CGI.pm |
62 |
Apache handler |
69 |
So if you want real performance and you ask me, the answer is
clear: take mod_perl and use what it already has (and it
really has a lot). | [reply] |
RE: Training wheels again
by merlyn (Sage) on Sep 04, 2000 at 00:56 UTC
|
| [reply] |
|
Ooops, sorry, of course I used Apache::DBI, Version 0.87 :).
| [reply] |
|
What makes me curious is the difference you see when
you stop using CGI.pm. I realize this won't translate to the
full-blown handler version of the script, but did you try loading CGI.pm
via default in mod_perl, or did you have
use CGI;
in your script?
"He's got about as much personality as a loaf of bread" -- Wally Pleasant, She's in love with a Geek | [reply] [d/l] |
|
|
|
|
RE: Training wheels again
by strredwolf (Chaplain) on Sep 04, 2000 at 22:23 UTC
|
I wouldn't be surprized if the hitcount went higher the less
junk and whatnot gets loaded before we can actually get to
do anything. I mean, CGI.pm is known to be a big huge
beast of code. There's CGI-lite.pm, but even better is a
short handler that goes through the GET or POST method and
gets the goods directly instead of fifty(exageration) levels
of abstraction.
Call me a hard-core purist. :)
--
Perl is intergalactic! WolfSkunks use it!
| [reply] |
|
I just stumbled across these modules yesterday. I haven't tried them yet, but they seem to be what you're looking for.
CGI::Deurl.pm and CGI::Enurl.pm This is a little module made for CGI scripting. It decodes the parameters passed to the CGI or an arbitrary URL encoded
string. It does nothing more, so it's much smaller and loads more quickly than CGI.pm.
| [reply] |
|
| [reply] |
RE: Training wheels again
by Anonymous Monk on Sep 06, 2000 at 05:00 UTC
|
Could you post your code for each of the scripts? I would be interested in looking at them as I have little experience with apache modules.
| [reply] |
RE: Training wheels again
by arturo (Vicar) on Sep 08, 2000 at 20:13 UTC
|
And, while I'm thinking of it ... OK, with Perl there's mod_perl to speed things up,
but, (and I realize these tools have the drawback of being proprietary), with PHP there are
the Zend Optimizer (at least with PHP4) and, if I am not mistaken a compiler for Zend.
To the extent that the latter is, for us on this end of things, vaporware, we can
perhaps disregard it (while keeping a watchful eye on its development).
The optimizer, OTOH, is available now. How about throwing that into the benchmarks?
"He's got about as much personality as a loaf of bread" -- Wally Pleasant, She's in love with a Geek
| [reply] |
|
Are benchmarks really *that* important between things like PHP and Perl? To me, the difference between serving 50 and 60 requests/second in irrelevant (50 and 200, maybe I would think more of). I generally care more about the response time on the user end.
Any of you who have talked to me, know I dislike PHP, and try to avoid it at all costs. But, when thinking in the scope of a large scale CGI application, it comes down to what is the better tool for the job. If you have zero backend to the app (unlikely), then maybe right now PHP would be a viable solution (just as Perl, or Cold Fusion, ASP or even Python would be, but who knows how all designers make their decisions). But, when you think of scalability, extendability, and having to do any backend work to help support the application, PHP, ASP and the like become less viable. There is nothing more messy than an application with multiple languages making it work. IMO, it is best to use one language for all of the software (ok, I do admit I use shell scripting for cron or setup scripts a lot). A front end in PHP, with a backend in Perl can really suck to manage (believe me, I know). When you think of this, and all the other things that go into designing a CGI app, benchmarks which are pretty close become less of a deciding factor in what tool to use.
</RANT>
Cheers,
KM
| [reply] |
RE: Training wheels again
by BastardOperator (Monk) on Sep 09, 2000 at 00:58 UTC
|
I don't suppose there's any chance that you could bring Java into the mix and see how a servlet under Apache compares? I don't mean to start everyone off bringing every language under the sun (pun intended) into the mix, but with Java pushing so hard to be _the_ solution for web/db applications, I'd love to see what it can do. Maybe if you post the code, I can whip something up, though my Java skills would most likely give a definite advantage to Perl and PHP ;). | [reply] |
|
I don't know any Java, but if you want to give it a try, here's the code I used for the script.
#!/usr/bin/perl -w
use DBI;
use strict;
# Create a new Apache request object
my $r = shift;
# Set up the parameter hash
my %q = $r->method eq "GET" ? $r->args : $r->content;
my $dbh = DBI->connect("DBI:mysql:adressen", "user", "secret", {RaiseE
+rror => 1});
$r->send_http_header;
print qq(<html>
<head>
<title>Adressbuch</title>
</head>
<body bgcolor="#ffffff">
);
print qq(
<CENTER>
<H1>Mein Adressbuch</H1>
<A HREF=addnew.pl>Neuer Eintrag</A><BR><BR>
<B>Suche nach:</B><BR>
<FORM METHOD="POST">
<INPUT TYPE=text NAME=list SIZE=30>
<INPUT TYPE=submit VALUE="Suche">
</FORM>
<P>
);
for ('A' .. 'Z') {
print "<a href=\"/perl/adressen/?list=$_\">$_</a> \n";
}
print "<br><br>\n";
if ($q{"list"}) {
my $search = $q{list};
my $sth = $dbh->prepare("SELECT * FROM list WHERE nachname LIKE ?
+ORDER BY nachname");
$sth->execute("$search%");
my ($nachname, $vorname, $strasse, $plz, $ort, $telefon1, $telefon
+2, $email, $id);
$sth->bind_columns(\($nachname, $vorname, $strasse, $plz, $ort, $t
+elefon1, $telefon2, $email, $id));
if ($sth->rows > 0) {
print "<BR><BR>";
print "<H3>Gefundene Einträge:</H3>";
print "<TABLE border=0 cellpadding=5>";
print "<tr align=center><td><b>Name</b></td><td><b>Straße</b><
+/td><td><b>PLZ Ort</b></td><td><b>Telefon</b></td><td><b>eMail</b></t
+d></tr>";
while ($sth->fetch) {
print "<TR>";
print "<TD valign=top><B>$nachname $vorname</B></TD>";
print "<TD valign=top>$strasse</TD>";
print "<TD valign=top>$plz $ort</TD>";
print "<TD valign=top>$telefon1<BR>";
print "$telefon2</TD>";
print "<TD valign=top><I><A HREF=mailto:$email>$email</A><
+/I>";
print "</TD>";
print "<TD align=right valign=top><FONT SIZE=-1><A HREF=ch
+ange.pl?id=$id>Ändern</A> ";
print "<A HREF=kill.pl?id=$id>Löschen</A></FONT></TD>
+</TR>";
print "<TR><TD colspan=7><HR></TD></TR>";
}
print "</table>\n";
} else {
print "<h3>Nichts gefunden.</h3>\n";
}
}
print "</center>\n";
print qq(
</body>
</html>
);
| [reply] [d/l] |
|
|