dougm 01/01/02 11:53:13 Added: pod modperl_design.pod Log: design doc Revision Changes Path 1.1 modperl-2.0/pod/modperl_design.pod Index: modperl_design.pod =================================================================== =head1 NAME mod_perl_design - notes on the design and goals of mod_perl-2.0 =head1 SYNOPSIS perldoc mod_perl_design =head1 DESCRIPTION notes on the design and goals of mod_perl-2.0 =head1 The Interpreter Pool this logic is only enabled if Perl is built with -Dusethreads otherwise, mod_perl will behave just as 1.xx, using a single interpreter, which is only useful if you're using the prefork mpm. when the server is started, a Perl interpreter is constructed, parsing any code specified in the configuration, just as 1.xx does. this interpreter is refered to as the "parent" interpreter. then, for the number of PerlInterpStart configured, a (thread-safe) clone of the parent interpreter is made (via perl_clone()) and added to a pool of interpreters. this clone copies any writeable data (e.g. the symbol table) and shares the compiled syntax tree. from my measurements of a startup.pl including a few random modules: use CGI (); use POSIX (); use IO (); use SelfLoader (); use AutoLoader (); use B::Deparse (); use B::Terse (); use B (); use B::C (); the parent adds 6M size to the process, each clone adds less than half that size, ~2.3M, thanks to the shared syntax tree. at request time, if any Perl*Handlers are configured, an available interpreter is selected from the pool. as there is a request_rec per thread, a pointer is saved in either the conn_rec->pool or request_rec->pool, which will be used for the lifetime of that request. for handlers that are called when threads are not running (PerlChild{Init,Exit}Handler), the parent interpreter is used. several configuration parameters control the interpreter pool management: =over 4 =item PerlInterpStart happens at startup time, the number of intepreters to clone =item PerlInterpMax if all running interpreters are in use, mod_perl will clone new interpreters to handle the request, up until this number of interpreters is reached. when Max is reached, mod_perl will block (via COND_WAIT()) until one becomes available (signaled via COND_SIGNAL()) =item PerlInterpMinSpare the minimum number of available interpreters this parameter will clone interpreters up to Max, before a request comes in =item PerlInterpMaxSpare mod_perl will throttle down the number of interpreters to this number as those in use become available =item PerlInterpMaxRequests the maximum number of requests an interpreter should serve, the interpreter is destroyed when the number is reached and replaced with a fresh one. =back =head2 tipool the interpreter pool is implemented in terms of a "tipool" (thread item pool), a generic api which can be reused for other data such as database connections. =head2 Virtual Hosts the interpreter management has been implemented in a way such that each VirtualHost can have its own parent Perl interpreter and/or mip. it is also possible to disable mod_perl for a given virtual host. =head2 Future at the moment, the interpreter pool is just a proof-of-concept implementation, to test that requests can be handled concurrently. the link-list implementation will certainly be optimized. and, some of the interpreter pool management might be moved into it's own thread. but the concept of mapping an interpreter clone to a thread will likely remain. a "garbage collector", which could also run in it's own thread, examining the padlists of idle interpreters and deciding to release and/or report large strings, array/hash sizes, etc., that Perl is keeping around as an optimization. =head1 Glue Code and Callbacks the code for hooking mod_perl in the various phases, including Perl*Handler directives is generated by the ModPerl::Code module. when a mod_perl hook is called for a given phase, the glue code has an index into the array of handlers, so it knows to return DECLINED right away if no handlers are configured, without entering the Perl runtime as 1.xx did. the handlers are also now stored in an ap_array_header_t, which is might lighter and faster than using a Perl AV, as 1.xx did. and again, keeps us out of the Perl runtime until we're sure we need to be there. Perl*Handlers are now "compiled", that is, the various forms of: PerlHandler MyModule (defaults to MyModule::handler or MyModule->handler) PerlHandler MyModule->handler PerlHandler $MyObject->handler PerlHandler 'sub { print "foo\n" }' are only parsed once, unlike 1.xx which parsed everytime the handler was used. there will also be an option to parse the handlers at startup time. note: this feature is currently not enabled with threads, as each clone needs its own copy of Perl structures. a "method handler" is now specifed using the `method' sub attribute, e.g. sub handler : method {}; instead of 1.xx's sub handler ($$) {} =head1 Build System the biggest mess in 1.xx is mod_perl's Makefile.PL, the majority of logic has been broken down and moved to the Apache::Build module. the Makefile.PL will construct an Apache::Build object which will have all the info it needs to generate scripts and Makefiles that apache-2.0 needs. regardless of what that scheme may be or change to, it will be easy to adapt to with build logic/variables/etc divorced from the actual Makefiles and configure scripts. the current state of the build system is far from complete, but just enough to build a libmodperl.a or libmodperl.so see 00README_FIRST if you're interested in giving it a whirl. =head1 SEE ALSO perlguts(1), perlembed(1), perlxs(1) =head1 AUTHOR Doug MacEachern