originally published on August 22, 2006 at
newsforge.com
revised November 7, 2006
Two very popular and widely used languages for building dynamic web
sites are Perl and PHP. They make up two thirds of the "P" in the Linux
Apache, MySQL, Perl/PHP/Python (LAMP) stack. How does their
performance, using mod_perl and mod_php, compare for everyday web
programming? I attempted to find out.
New in the rematch
In the rematch, I updated the Perl HTML code based on suggestions
from comments to the orignal article. It should create a more accurate
comparison with PHP. Though the main goal is to
compare the performance of mod_perl and mod_php, I added a TCL
CGI program to compare against Perl CGI. Finally, the hardware
used for testing was significantly faster.
The machine
My new test bed was a DELL PowerEdge 2850 server with the
following specifications and software:
3.2 Ghz Intel Xeon
4G RAM
Red Hat Enterprise Linux 3
Apache 2.0.46
MySQL 3.23.58
Perl 5.8.0
PHP 4.3.2
TCL 8.3.5
This system is a monster compared to the 700
Mhz server from the original test. I expected the results
to reflect it.
The method
For testing, I created two programs in Perl and two in PHP that produced
identical results using logic as similar as I could make them. One
program generates HTML and the second reads and updates a MySQL
database.
For the HTML generation test, each program counts from 1 to 1024 and
writes a line of HTML to the screen. I choose five different run loads:
1 HTTP request
100 HTTP requests (serially)
100 HTTP requests (10 concurrently)
1000 HTTP requests (serially)
1000 HTTP requests (10 concurrently)
For the MySQL test, I ran a single HTTP request that read and updated
5000 records in a table. To communicate with MySQL, I used the standard
PHP interface and Perl DBI. Here is the structure of the test table:
+----------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+----------+------+-----+---------+----------------+
| id | int(11) | | PRI | NULL | auto_increment |
| junktext | char(30) | YES | | NULL | |
+----------+----------+------+-----+---------+----------------+
Each of the 5000 records was initialized as follows:
+-------+--------------------------------+
| id | junktext |
+-------+--------------------------------+
| 1 | XXXXXXXXX0XXXXXXXXX0XXXXXXXXX0 |
+-------+--------------------------------+
The programs read each record from the table, converted the
junktext column to lower case, then wrote it back. The goal was
to test the database drivers and overhead in Perl and PHP.
I performed no tuning on any component of the LAMP stack as delivered
from Red Hat. In a hosted environment, being able to change system
components is a rare luxury. For your reading pleasure, I present the Perl HTML test code, Perl MySQL test code,
PHP HTML test code,
PHP MySQL test
code, and
TCL HTML test code.
Results
I ran benchmarks using the ApacheBench program (2.0.40) -- part of the
standard Apache package -- which measures the time for each HTTP
request to be processed and reports totals and averages. I ran each
benchmark three times and took the mean of the results.
All tests were run on an internal network,
where both client and server were isolated from the vagaries
of the Internet.
As a baseline, I included the execution of each Perl program
as a regular Common Gateway Interface (CGI) program. CGI was one of the
first methods of creating dynamic web content. There are still many CGI
programs working their magic on the web. Since I have been coding
some TCL lately, I also ran the HTML tests using TCL CGI.
The problem with CGI is that it forks a new process and loads a copy of
the Perl or TCL interpreter for each request, using gobs of memory. Mod_perl
includes the Perl interpreter within Apache. Both mod_perl and mod_php
run inside the Apache process that is handling the page, providing more
efficient execution.
Following are the results of the CGI, mod_perl, and mod_php tests.
The number after HTTP in column one indicates the number of
requests for that test. A number followed by a c indicates that
10 concurrent requests were run for that test. All times are in seconds
(lower is better).
Additional TCL note: I did not run the MySQL test with TCL
because TCL does not come with a native MySQL interface.
Unlike Perl and PHP, you have to install third party software
to talk to MySQL. This highlights a weakness of TCL. The native interfaces that
ship other languages reflect to some extent the depth of their
communities and popularity. That doesn't mean TCL can't talk to MySQL
or do anything any other language can, it just means it takes more
effort.
HTML generation tests
| |
TCL CGI |
Perl CGI |
mod_perl |
mod_php |
| HTTP-1 |
0.2962 |
0.6515 |
0.5339 |
0.5072 |
| HTTP-100 |
2.8881 |
5.3519 |
0.7068 |
0.5396 |
| HTTP-100c |
2.4584 |
3.9263 |
0.3806 |
0.4048 |
| HTTP-1000 |
29.4226 |
52.3125 |
5.5057 |
5.4534 |
| HTTP-1000c |
24.8832 |
39.2487 |
3.96627 |
4.3705 |
MySQL test
| |
Perl CGI |
mod_perl |
mod_php |
| MySQL-rw |
0.5680 |
0.5478 |
0.4206 |
Conclusions and commentary
I need to hedge my observations somewhat because using object oriented
features of either language, adding third party modules, or sessions to
the mix could alter the outcome.
That said, the results of these tests show that for serial HTML
generation. PHP (mod_php) was slightly faster than Perl (mod_perl). But,
for concurrent HTML generation, the more likely real world
scenario, Perl was slightly faster than PHP.
I attribute the better showing for Perl in the rematch to the code
rewrite. The mod_perl code cache really shined as the load
increased. In the MySQL test, PHP maintained a small edge over Perl.
I suspect the MySQL results reflect the extra overhead of the Perl
DBI interface versus the direct interface from PHP. However, DBI seems
to be the standard connection method for databases in Perl.
Both mod_perl and mod_php have an enormous performance advantage over
TCL CGI and Perl CGI. I was not surprised to see TCL CGI perform better
than Perl CGI since the TCL interpreter is much smaller than Perl.
CGI not only doesn't scale very well, but gains little advantage from
concurrency. Under load, it could bring a server to its knees.
One unique feature of mod_perl is the ability to embed Perl code in the
Apache configuration file. This provides more options for dynamic
server configuration. To my knowledge, PHP does not have an equivalent
feature.
PHP provided consistent performance. It was
designed from the start as a dynamic web language and excels in that
role.
For tweakers, there are a number of ways to increase Perl and PHP
performance with Apache. For Perl, there is the FastCGI
module. For PHP, there are proprietary, free (as in beer), and
open source PHP cache
accelerators. These are advanced options and require additional
work to set up.
No lose scenario
Both Perl and PHP are robust and powerful languages for creating web
applications. They both offer large libraries of code, database
drivers, and third party add-ons. For small and medium sized
applications, the difference would be hard to notice. Extrapolating
these results to high traffic applications is not a good idea because
too many other factors come into play. Whether you opt for Perl or PHP
in your web development adventures, you win.

This work is licensed under a
Creative Commons Attribution-NonCommercial 2.5 License.