Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Training wheels again

by le (Friar)
on Sep 04, 2000 at 00:43 UTC ( [id://30945]=monkdiscuss: print w/replies, xml ) Need Help??

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

Replies are listed 'Best First'.
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).

RE: Training wheels again
by merlyn (Sage) on Sep 04, 2000 at 00:56 UTC
      Ooops, sorry, of course I used Apache::DBI, Version 0.87 :).

        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

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!

      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.

        Yeah, but how about a "built-in" parser? I did that for the American Geophysical Union a few years ago, reusing some old code.

        --
        Perl is intergalactic! WolfSkunks use it!

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.
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

      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

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 ;).
      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>&nbsp;\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>&Auml;ndern</A>&nbsp;&nbsp;"; print "<A HREF=kill.pl?id=$id>L&ouml;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> );

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: monkdiscuss [id://30945]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (2)
As of 2024-04-20 03:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found