httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Mark J Cox <>
Subject Embedding perl in the HTTP server (fwd)
Date Mon, 25 Mar 1996 15:16:21 GMT
Looks interesting...


---------- Forwarded message ----------
Date: Mon, 25 Mar 1996 14:57:22 +0100
From: Gisle Aas <>
Subject: Embedding perl in the HTTP server

This weekend I have been playing with an Apache module that embeds a perl
interpreter in the HTTP server.  The benefit of this is that we are able to
run scripts without going through the expensive (fork/exec/parameter
passing/parsing, etc.) CGI interface.  The scripts will run faster and they
have direct access to the complete C API of the server.

My current approach is that I will allocate and construct a new perl for
each request.  The interpreter will then parse and run a perl script and we
finally destruct the perl interpreter in order to free memory consumed.  The
script must call the Apache API to send data back to the client.  Printing
(to STDOUT) from the perl script goes to the server's STDOUT, not back to
the client.  A simple apache perl script will look like this:

    Apache->bootstrap; @request_recPtr::ISA = 'Apache';  # Some magic


    $req->write_client_block("<h1>This is a stupid test</h1>\n");

This does the same as the following CGI script:

    print "Content-Type: text/html\n\n";
    print "<h1>This is a stupid test</h1>\n";

All the normal input parameters are available as perl variables before the
script starts up.  These variables are present when the script starts:

   $req              The request object reference
   $method           GET, POST, HEAD,...
   $protocol         HTTP/1.0
   %headers_in       Addition headers present in the request
   $args             The QUERY_STRING
   @args             Parsed and unescaped QUERY_STRING (key, value) pairs

The module (like the CGI perl modules) will transparently read the POST
'application/x-www-form-urlencoded' content and pass it on as $args/@args so
that the perl script does not have to.

The script can trigger errors by exit'ing with a HTTP status code (the perl
exit value is used as return value from the apache handler).

   exit 403;  # Forbidden

Complete API listing:

   # Control headers
   $req->set_header_out("WWW-Authenticate", "Basic");
   $req->set_err_headers_out("WWW-Authenticate", "Basic");
   $req->send_http_header;  # actually start a reply

   # Talk to the client
   $req->read_client_block($buf, $size);
   $req->send_fd(FILE);    # just send the whole thing file

   ## The server error log
   $req->log_reason("Because I felt like it", __FILE__);
   $req->log_error("Some text that goes in the error_log");


I even tried to benchmark how well this new embedded interpreter performs.
These are the results using those simple scripts shows above (which just
outputs <h1>This is a stupid test</h1>).

                            test.html   test.cgi

Apache/1.0.3                  0.164s     0.531s    0.170s
NCSA/1.4.2                    0.165s     0.243s
Netscape-Communications/1.1   0.107s     0.273s

The times are average response time per request after several runs of the
script below.  The httpd servers was running on a Sparc4 workstation.  As
you can see the embedded perl performs quite well.  It is almost as quick
as just sending a static file (but then there is not much perl parsing
going on).

The test also shows that the Apache server does a very bad job at invoking
CGI scripts.  I was surprised to find that it was sooo much slower than NCSA
or Netscape.  I believed that Apache should be faster since this is what
they said at <URL:>: "is much faster than
NCSA 1.3, more efficient and faster than 1.4/1.5 too."  Does anybody else
has any experience on this matter?

The client test script I used was this one:

  #!/local/perl/bin/perl -w
  use LWP::Simple;
  for (1..100) {
      $a = get "";
      print $a;

Speeding it up even more: The perl compiler will hopefully be of help when
it comes along.  Another approach is to let the embedded perl interpreter
load the scripts initially and then we just call a perl subroutine to
handle the requests.  This should be very fast, but I don't know how we
could manage to free the memory consumed during execution of the request.


If you want to take a look, then the new Apache module should be available
from this address (please don't mirror or publicise widely because this is
just a proof-on-concept implementation):

You will need perl5.002 and apache1.0.3 to get this up and running.

I would like to get some feedback on this module, its interface and perhaps
ways to make this run even faster?  Do you know about similar stuff?


View raw message