You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Ken Simpson <ks...@mailchannels.com> on 2005/12/20 23:42:12 UTC
Solving mod_perl scalability issues for lots of slow connections
[note: Subject changed from "go crazy with me" -- LoL]
> I'd also like to hear what people are doing when the apache model has
> scaling problems. We have one problematic project here: we're a
> gateway and must server a high number of very slow customers to a high
> number of very slow feeds. Ideally we would run this in an event loop
> or in coroutines/continuations style, but we have not yet tried that
> out, mainly because so much of our infrastructure relies on everything
> being apache. Is there something in apache2 that would make our lives
> easier? (we have not yet switched to apache2 at all)
Hi Andreas,
I wonder if our asynchronous system could help. As I mentioned in a post
earlier today, it's not yet released but we have been considering
doing that perhaps in January when we have more time to polish it up
for general consumption.
Our email connection management software starts life as a mod_perl
app, but forks a tiny Event::Lib based pure-Perl app after
configuration to handle all the slow connections. A pool of mp2
processes is kept around, running a very simple protocol handler to
receive and process short running but CPU-intensive requests from the
IO subsystem.
The nice thing about this architecture is that it still gives us
access to the goodies mp2 has to offer -- such as application
configuration -- while also allowing us to keep the number of Perl
interpreters to a minimum by using a single process, event-driven IO
model.
Alas, if only the Perl interpreter was truly thread safe and did not
clone a new interpreter for each thread, we could just use
threads... Those Python people have it good in some ways.
TTUL
Ken
--
MailChannels: Assured Messaging (TM) | http://mailchannels.com
--
Suite 203, 910 Richards St.
Vancouver, BC, V6B 3C1, Canada
Direct: +1-604-729-1741
Re: Solving mod_perl scalability issues for lots of slow connections
Posted by Tagore Smith <ta...@tagoresmith.com>.
Andreas J. Koenig wrote:
>>>>>>On Tue, 20 Dec 2005 14:42:12 -0800, Ken Simpson <ks...@mailchannels.com> said:
>
>
> > [note: Subject changed from "go crazy with me" -- LoL]
> >> I'd also like to hear what people are doing when the apache model has
> >> scaling problems. We have one problematic project here: we're a
> >> gateway and must server a high number of very slow customers to a high
> >> number of very slow feeds. Ideally we would run this in an event loop
> >> or in coroutines/continuations style, but we have not yet tried that
> >> out, mainly because so much of our infrastructure relies on everything
> >> being apache. Is there something in apache2 that would make our lives
> >> easier? (we have not yet switched to apache2 at all)
I have had similar problems in the past, and my initial thoughts were
not that dissimilar to yours- I was tempted to go with a scheme solution
based on continuations, but in the end I wrote a bit of Erlang to proxy
to the backend server (it was the first serious Erlang I had written,
and it was surprisingly easy to do). It has worked well for us, and the
ratio of peak connections to revenue (and thus hardware budget) on this
system is pretty off-kilter. Not for everyone, I'm sure, as maintenance
depends on always having someone who can deal with Erlang on hand, but
it is one way, among many, I'm sure, to go. Apologies if I seem to be
evangelizing something non-perl here- the backend was mod_perl ;). I
would think that much the same result could be achieved using an
asynchronous setup. Perhaps it is irrelevant- if you are truly,
completely tied to Apache, then I'm afraid my response is more noise
than signal- but it might be worth reassessing whether or not that is
actually the case.
T Smith
Re: $r->print doesn't work in Apache2/MP2/Libapreq2?
Posted by Frank Wiles <fr...@wiles.org>.
On Wed, 21 Dec 2005 10:15:49 -0600
Frank Wiles <fr...@wiles.org> wrote:
> You want to do this instead:
>
> sub handler {
> my $r = shift;
> my $req = Apache2::Request->new( $r );
> my %ins = &process_input($r);
>
> $r->print.....
> }
Of course I notice the typo as the message is sending and I'm too
slow to hit cancel!
That should be my %ins = &process_input( $req ) not $r.
---------------------------------
Frank Wiles <fr...@wiles.org>
http://www.wiles.org
---------------------------------
Re: $r->print doesn't work in Apache2/MP2/Libapreq2?
Posted by Harry Zhu <ha...@greatlodge.com>.
Thanks for the quick reply. use Apachd2::RequestIO solve the problem (I am
trying to migrate from MP1 to MP2 and I thought Apache2::Request would
already did that.)
Harry
----- Original Message -----
From: "Frank Wiles" <fr...@wiles.org>
To: "Harry Zhu" <ha...@greatlodge.com>
Cc: <mo...@perl.apache.org>
Sent: Wednesday, December 21, 2005 10:15 AM
Subject: Re: $r->print doesn't work in Apache2/MP2/Libapreq2?
> On Wed, 21 Dec 2005 10:06:29 -0600
> "Harry Zhu" <ha...@greatlodge.com> wrote:
>
>>
>> sub handler {
>> my $r = Apache2::Request->new(shift);
>> my %ins = &processInput($r);
>> ...
>> $r->print($html);
>> return OK;
>> }
>>
>> Can't locate auto/Apache2/Request/print.al in @INC (@INC contains:
>> /www/modperl /usr/local/lib/perl5/5.8.7/i686-linux
>> /usr/local/lib/perl5/5.8.7
>> /usr/local/lib/perl5/site_perl/5.8.7/i686-linux
>> /usr/local/lib/perl5/site_perl/5.8.7 /usr/local/lib/perl5/site_perl .
>> /usr/local/apache2) at /www/modperl/Sys/Handler.pm line 81
>>
>> if change "$r->print" to "print", it works fine. A quick browsing
>> through the MP2 documents for the example handler, some using print
>> while others using $r->print (without Apache2::Request), does
>> $r->print under Apache2::Request?
>>
>
> You probably don't want to do that. Apache2::Request is a wrapper
> for libapreq for parsing query parameters.
>
> You want to do this instead:
>
> sub handler {
> my $r = shift;
> my $req = Apache2::Request->new( $r );
> my %ins = &process_input($req);
>
> $r->print.....
> }
>
> You'll also need to use or preload Apachd2::RequestIO as this provides
> the print function.
>
> Hope this helps.
>
> ---------------------------------
> Frank Wiles <fr...@wiles.org>
> http://www.wiles.org
> ---------------------------------
>
>
>
>
> --
> No virus found in this incoming message.
> Checked by AVG Free Edition.
> Version: 7.1.371 / Virus Database: 267.14.3/209 - Release Date: 12/21/2005
>
>
Re: $r->print doesn't work in Apache2/MP2/Libapreq2?
Posted by Frank Wiles <fr...@wiles.org>.
On Wed, 21 Dec 2005 10:06:29 -0600
"Harry Zhu" <ha...@greatlodge.com> wrote:
>
> sub handler {
> my $r = Apache2::Request->new(shift);
> my %ins = &processInput($r);
> ...
> $r->print($html);
> return OK;
> }
>
> Can't locate auto/Apache2/Request/print.al in @INC (@INC contains:
> /www/modperl /usr/local/lib/perl5/5.8.7/i686-linux
> /usr/local/lib/perl5/5.8.7 /usr/local/lib/perl5/site_perl/5.8.7/i686-linux
> /usr/local/lib/perl5/site_perl/5.8.7 /usr/local/lib/perl5/site_perl .
> /usr/local/apache2) at /www/modperl/Sys/Handler.pm line 81
>
> if change "$r->print" to "print", it works fine. A quick browsing
> through the MP2 documents for the example handler, some using print
> while others using $r->print (without Apache2::Request), does
> $r->print under Apache2::Request?
>
You probably don't want to do that. Apache2::Request is a wrapper
for libapreq for parsing query parameters.
You want to do this instead:
sub handler {
my $r = shift;
my $req = Apache2::Request->new( $r );
my %ins = &process_input($r);
$r->print.....
}
You'll also need to use or preload Apachd2::RequestIO as this provides
the print function.
Hope this helps.
---------------------------------
Frank Wiles <fr...@wiles.org>
http://www.wiles.org
---------------------------------
Re: $r->print doesn't work in Apache2/MP2/Libapreq2?
Posted by Issac Goldstand <ma...@beamartyr.net>.
That's because the $r you get from shift isn't interchangable with the
$r you get from Apache2::Request (which I think is deprecated anyway).
Try doing
sub handler {
my $r = shift;
my $q = Apache2::Request->new($r);
my %ins = &processInput($q);
...
$r->print($html);
return OK;
}
Harry Zhu wrote:
>
> sub handler {
> my $r = Apache2::Request->new(shift);
> my %ins = &processInput($r);
> ...
> $r->print($html);
> return OK;
> }
>
> Can't locate auto/Apache2/Request/print.al in @INC (@INC contains:
> /www/modperl /usr/local/lib/perl5/5.8.7/i686-linux
> /usr/local/lib/perl5/5.8.7
> /usr/local/lib/perl5/site_perl/5.8.7/i686-linux
> /usr/local/lib/perl5/site_perl/5.8.7 /usr/local/lib/perl5/site_perl .
> /usr/local/apache2) at /www/modperl/Sys/Handler.pm line 81
>
> if change "$r->print" to "print", it works fine. A quick browsing
> through the MP2 documents for the example handler, some using print
> while others using $r->print (without Apache2::Request), does $r->print
> under Apache2::Request?
>
> Harry Zhu
>
>
>
> Apache/2.2.0 (Unix) mod_ssl/2.2.0 OpenSSL/0.9.7a DAV/2
> mod_apreq2-20050712/2.1.3-dev mod_perl/2.0.2 Perl/v5.8.7
> and
> perl_module (shared)
> apreq_module (shared)
>
>
> perl -V
> Summary of my perl5 (revision 5 version 8 subversion 7) configuration:
> Platform:
> osname=linux, osvers=2.6.9-5.el, archname=i686-linux
> uname='linux deskweb1.glworkgroup 2.6.9-5.el #1 wed jan 5 19:22:18
> est 2005 i686 i686 i386 gnulinux '
> config_args='-des -Uusethreads'
> hint=recommended, useposix=true, d_sigaction=define
> usethreads=undef use5005threads=undef useithreads=undef
> usemultiplicity=undef
> useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
> use64bitint=undef use64bitall=undef uselongdouble=undef
> usemymalloc=n, bincompat5005=undef
> Compiler:
> cc='cc', ccflags ='-fno-strict-aliasing -pipe -I/usr/local/include
> -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm',
> optimize='-O2',
> cppflags='-fno-strict-aliasing -pipe -I/usr/local/include
> -I/usr/include/gdbm'
> ccversion='', gccversion='3.4.3 20041212 (Red Hat 3.4.3-9.EL4)',
> gccosandvers=''
> intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
> d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
> ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t',
> lseeksize=8
> alignbytes=4, prototype=define
> Linker and Libraries:
> ld='cc', ldflags =' -L/usr/local/lib'
> libpth=/usr/local/lib /lib /usr/lib
> libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc
> perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
> libc=/lib/libc-2.3.4.so, so=so, useshrplib=false, libperl=libperl.a
> gnulibc_version='2.3.4'
> Dynamic Linking:
> dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
> cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'
>
>
> Characteristics of this binary (from libperl):
> Compile-time options: USE_LARGE_FILES
> Built under linux
> Compiled at Oct 20 2005 14:29:14
> @INC:
> /usr/local/lib/perl5/5.8.7/i686-linux
> /usr/local/lib/perl5/5.8.7
> /usr/local/lib/perl5/site_perl/5.8.7/i686-linux
> /usr/local/lib/perl5/site_perl/5.8.7
> /usr/local/lib/perl5/site_perl
$r->print doesn't work in Apache2/MP2/Libapreq2?
Posted by Harry Zhu <ha...@greatlodge.com>.
sub handler {
my $r = Apache2::Request->new(shift);
my %ins = &processInput($r);
...
$r->print($html);
return OK;
}
Can't locate auto/Apache2/Request/print.al in @INC (@INC contains:
/www/modperl /usr/local/lib/perl5/5.8.7/i686-linux
/usr/local/lib/perl5/5.8.7 /usr/local/lib/perl5/site_perl/5.8.7/i686-linux
/usr/local/lib/perl5/site_perl/5.8.7 /usr/local/lib/perl5/site_perl .
/usr/local/apache2) at /www/modperl/Sys/Handler.pm line 81
if change "$r->print" to "print", it works fine. A quick browsing through
the MP2 documents for the example handler, some using print while others
using $r->print (without Apache2::Request), does $r->print under
Apache2::Request?
Harry Zhu
Apache/2.2.0 (Unix) mod_ssl/2.2.0 OpenSSL/0.9.7a DAV/2
mod_apreq2-20050712/2.1.3-dev mod_perl/2.0.2 Perl/v5.8.7
and
perl_module (shared)
apreq_module (shared)
perl -V
Summary of my perl5 (revision 5 version 8 subversion 7) configuration:
Platform:
osname=linux, osvers=2.6.9-5.el, archname=i686-linux
uname='linux deskweb1.glworkgroup 2.6.9-5.el #1 wed jan 5 19:22:18 est
2005 i686 i686 i386 gnulinux '
config_args='-des -Uusethreads'
hint=recommended, useposix=true, d_sigaction=define
usethreads=undef use5005threads=undef useithreads=undef
usemultiplicity=undef
useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=undef use64bitall=undef uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='cc', ccflags
='-fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
-I/usr/include/gdbm',
optimize='-O2',
cppflags='-fno-strict-aliasing -pipe -I/usr/local/include -I/usr/include/gdbm'
ccversion='', gccversion='3.4.3 20041212 (Red Hat 3.4.3-9.EL4)',
gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
alignbytes=4, prototype=define
Linker and Libraries:
ld='cc', ldflags =' -L/usr/local/lib'
libpth=/usr/local/lib /lib /usr/lib
libs=-lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc
perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
libc=/lib/libc-2.3.4.so, so=so, useshrplib=false, libperl=libperl.a
gnulibc_version='2.3.4'
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'
Characteristics of this binary (from libperl):
Compile-time options: USE_LARGE_FILES
Built under linux
Compiled at Oct 20 2005 14:29:14
@INC:
/usr/local/lib/perl5/5.8.7/i686-linux
/usr/local/lib/perl5/5.8.7
/usr/local/lib/perl5/site_perl/5.8.7/i686-linux
/usr/local/lib/perl5/site_perl/5.8.7
/usr/local/lib/perl5/site_perl
Re: Solving mod_perl scalability issues for lots of slow connections
Posted by "Andreas J. Koenig" <an...@franz.ak.mind.de>.
>>>>> On Tue, 20 Dec 2005 14:42:12 -0800, Ken Simpson <ks...@mailchannels.com> said:
> [note: Subject changed from "go crazy with me" -- LoL]
>> I'd also like to hear what people are doing when the apache model has
>> scaling problems. We have one problematic project here: we're a
>> gateway and must server a high number of very slow customers to a high
>> number of very slow feeds. Ideally we would run this in an event loop
>> or in coroutines/continuations style, but we have not yet tried that
>> out, mainly because so much of our infrastructure relies on everything
>> being apache. Is there something in apache2 that would make our lives
>> easier? (we have not yet switched to apache2 at all)
> Hi Andreas,
> I wonder if our asynchronous system could help.
Possibly. I'm looking forward to the release and watching thisspace:)
--
andreas
Re: Solving mod_perl scalability issues for lots of slow connections
Posted by Jonathan Vanasco <jo...@2xlp.com>.
On Dec 22, 2005, at 1:51 PM, Perrin Harkins wrote:
> You're pretty much describing lighthttpd + FastCGI. However, I don't
> think it supports SSL and it obviously has no support for any other
> apache modules or for hooking into request stages (although FastCGI
> has
> some things, like authentication handlers).
it does support ssl , but the configuration is a bit awkward.
it has a weird equivalent of apache request stages, which can be
accessed via custom plugins, and *might* be accessed via other methods.
more is here:
state engine:
http://lighttpd.net/documentation/state.html
plugin system:
http://lighttpd.net/documentation/plugins.html
personally, i've found lighttpd to be really good for:
serving small static files
proxying to apache_modperl if you need no request stage processing
and you want something lighter than apache and simpler than squid
running php (lighttpd + php5cgi + fcgi + eaccelerator compiled cache
on my freebsd6 box is considerably faster / more efficient w/
resources than every apache2 setup i've tried. i've found similar
operations in mod_perl under apache2 are faster than that though.)
its really not good for:
most other things that apache2/mp2 is freaking excellent at
fortunately for me (and not you) those are things that i need, but
you most likely don't
now back to mod_perl
Re: Solving mod_perl scalability issues for lots of slow
connections
Posted by Perrin Harkins <pe...@elem.com>.
On Thu, 2005-12-22 at 12:22 -0600, David Nicol wrote:
> To make a 3TAM system work like mod_perl, never mind the hooks
> into the various apache request service stages, every long-running
> perl script could be interpreted into one of serveral mp_like interpreters
> at the handler layer, or even every mp script could become its own
> small pool of processes waiting for activation.
You're pretty much describing lighthttpd + FastCGI. However, I don't
think it supports SSL and it obviously has no support for any other
apache modules or for hooking into request stages (although FastCGI has
some things, like authentication handlers).
- Perrin
Re: Solving mod_perl scalability issues for lots of slow connections
Posted by David Nicol <da...@gmail.com>.
> Ideally we would run this in an event loop
Anyone is welcome to take over maintenance of http::server::singlethreaded
and add apache/mp features to it, then there would be big monolithic
perl web-servers. Blocking in the request handlers would remain a problem,
but not anything that couldn't be solved with Socket::PassAccessRights and
a pool of external worker processes that are responsible for setting up
a fd for the new request, passing the fd back to the main program, then
doing whatever is needed to service the request.
I have set something similar up at my job, but it is not releasable
and not directly applicable to rejiggering singlethreaded into a better
more scalable mod_perl.
So here's the "three tier asynchronous model" (3TAM):
Main Select Loop
handles all connections from remote clients, including
relaying data from worker processes. Very fast data
can be served directly, anything that might block is
passed to an available worker.
Worker Process Pool
these processes generate and pass file descriptors
and then become handlers, by forking, or by passing
the other side of a socketpair to a handler
Handler Processes
these do blocking things, like groveling through twenty million
nonindexed database records, and report their findings
to their STDOUT, which happens to be a socketpair
that is read by the MSL.
The middle layer is there to protect the main loop from ever having
to fork().
To make a 3TAM system work like mod_perl, never mind the hooks
into the various apache request service stages, every long-running
perl script could be interpreted into one of serveral mp_like interpreters
at the handler layer, or even every mp script could become its own
small pool of processes waiting for activation. Some benchmarking
would need to be done WRT the optimum amount of code to have
in a long-lived perl interpreter instance.
mod_perl:
each apache thread includes a perl interpreter which has loaded
into it the entire mod_perl feature set of the web server, each in
its own name space. Pool size is managed by apache threads.
proposed 3TAM:
each 3TAM_perl script would be wrapped into a long-lived program
that lives in its own process pool of size greater than or equal to two,
which is capable of forking when the script is used heavily and
exiting when there are too many free ones. Pool size is managed
with a finer granularity: the individual script.
Crazy enough for you?
--
David L Nicol
This is the dawning of the age of asparagus
Re: Solving mod_perl scalability issues for lots of slow connections
Posted by David Nicol <da...@gmail.com>.
On 12/24/05, Bob Ippolito <bo...@redivi.com> wrote:
> I don't think any of this is really relevant to mod_perl though, it's bound
> to the way Apache works.
But if a mod_perl-compatible environment were constructed that did not depend
on apache, would that be on-topic for this list?
Happy new year
Re: Solving mod_perl scalability issues for lots of slow connections
Posted by Bob Ippolito <bo...@redivi.com>.
On Dec 21, 2005, at 1:26 PM, Jonathan wrote:
> On Dec 21, 2005, at 12:23 PM, Perrin Harkins wrote:
>
>> On Tue, 2005-12-20 at 14:42 -0800, Ken Simpson wrote:
>>> Alas, if only the Perl interpreter was truly thread safe and did not
>>> clone a new interpreter for each thread, we could just use
>>> threads... Those Python people have it good in some ways.
>>
>> Not that good really. As I understand it, the Python interpreter
>> has a
>> global lock when using threads. That's probably part of the
>> reason why
>> the most popular server framework for Python, Twisted, is single-
>> threaded.
>
> I fwd'd this to a friend with commit access to twisted. hopefully
> i'll get a response on clarification.
>
> But from what I understand, the Twisted networking framework works
> like this:
> The twisted 'reactor' is single threaded. It uses select by
> default, you can use poll. The docs suggest that one can specify a
> multithreaded reactor, but I'm not quite sure.
> The docs also specify a threadpool, and it seems that the deferred
> callback system has been implemented into it.
>
> CherryPy is a http server framework for python, and that supports a
> single or multi threaded server mode.
>
Twisted does all network I/O multiplexed in one thread by way of
something like select, poll, epoll, kqueue, WaitForMultipleEvents, or
whatever other model is implemented by that reactor. You can use as
many other threads as you want for doing whatever else you want, but
if you will get callbacks on the reactor thread and you must register
callbacks on the reactor thread. This model has been shown to scale
extremely well (in any language).
Python's GIL gets released by most code that does a lot of work or
waits on a resource in C. This means that when you're doing select
(), a database call, etc. other threads get a chance to run. Python
bytecode runs in separate OS threads, but the GIL causes them to run
round-robin. This does two things: it makes it relatively easy to
write threaded programs in Python, and it saves on memory as you only
need a threadstate data structure per thread, not a whole interpreter.
Interpreter-per-processor is of course the most scalable model in
either language, because then you can run bytecode in parallel. It's
most portable and probably easiest to do this in separate processes
rather than threads, especially considering that the multiprocess
model can be made to scale across machines too.
I don't think any of this is really relevant to mod_perl though, it's
bound to the way Apache works.
-bob
Re: Solving mod_perl scalability issues for lots of slow connections
Posted by Jonathan <jv...@2xlp.com>.
I fwd'd this to a friend with commit access to twisted. hopefully
i'll get a response on clarification.
But from what I understand, the Twisted networking framework works
like this:
The twisted 'reactor' is single threaded. It uses select by
default, you can use poll. The docs suggest that one can specify a
multithreaded reactor, but I'm not quite sure.
The docs also specify a threadpool, and it seems that the deferred
callback system has been implemented into it.
CherryPy is a http server framework for python, and that supports a
single or multi threaded server mode.
On Dec 21, 2005, at 12:23 PM, Perrin Harkins wrote:
> On Tue, 2005-12-20 at 14:42 -0800, Ken Simpson wrote:
>> Alas, if only the Perl interpreter was truly thread safe and did not
>> clone a new interpreter for each thread, we could just use
>> threads... Those Python people have it good in some ways.
>
> Not that good really. As I understand it, the Python interpreter
> has a
> global lock when using threads. That's probably part of the reason
> why
> the most popular server framework for Python, Twisted, is single-
> threaded.
>
> - Perrin
>
Re: Solving mod_perl scalability issues for lots of slow
connections
Posted by Perrin Harkins <pe...@elem.com>.
On Tue, 2005-12-20 at 14:42 -0800, Ken Simpson wrote:
> Alas, if only the Perl interpreter was truly thread safe and did not
> clone a new interpreter for each thread, we could just use
> threads... Those Python people have it good in some ways.
Not that good really. As I understand it, the Python interpreter has a
global lock when using threads. That's probably part of the reason why
the most popular server framework for Python, Twisted, is single-
threaded.
- Perrin