Hi All,
I have a few questions about the performance of PHP web applications under
load and I would appreciate if there is anyone that would like to share
their experiences in terms of any benchmarks or observations.
Background Information
In multi-process environments, such as FastCGI, Apache Prefork MPM etc, PHP
needs to execute the MINIT and MSHUTDOWN functions for all loaded extensions
on every request.
In a multi-threaded environment, such as Apache Worker MPM, with Zend Thread
Safety is enabled,
PHP only needs to execute MINIT and MSHUTDOWN functions once for each
extension and not each time a new thread is created to serve a request.
It is also more expensive to create new processes than to create new
threads.
In one-on-one comparisons between scripts executed only once in ZTS mode and
scripts executed once in non-ZTS mode,
I noticed that the one in non-ZTS mode was slightly faster and this seems to
be the main reason why most people go with the non-ZTS enabled setups.
But the reason for this slight difference in speed is because of the
differences in the data structure for globals for ZTS and non-ZTS modes.
Other reasons people have cited for going with non-threaded setups include
stability which I guess we should not really be concerned about if
non-threadsafe extensions are excluded.
Since it is generally more expensive to create new processes than new
threads, I believe that under high load, php in ZTS mode (multi-threaded
environment) will perform better than an identical setup in NTS mode
(multi-process).
Problem
I noticed that Zend Server is using PHP in FastCGI mode (multi-process NTS)
and I am contemplating setting up apache in worker mode (threaded mode) and
compiling php in ZTS mode instead.
Has anyone performed any load tests benchmarks comparing the two setups
(Multi-Process vs Multi-Threaded)?
Are there PHP extensions that cause issues in threaded environments that I
should avoid?
Are there any internals information or any other reasons why I should choose
ZTS over NTS or vice versa?
Any useful feedback will be highly appreciated.
Thanks.
--
°O°
"Good Enough" is not good enough.
To give anything less than your best is to sacrifice the gift.
Quality First. Measure Twice. Cut Once.
http://www.israelekpo.com/
This is just personal experience and observation but...
We are running Apache Worker with PHP safely by using PHP-FPM rather than via a shared object, so we don't have to worry about thread safety in the PHP component but can have apache multithreaded. I realise this isn't actually multi-threaded PHP but multi-process instead but s means we don't have to worry about making sure extensions etc are thread safe.
I haven't got the benchmarks to hand but I might able to dig some of them out if you would like. Apache Worker + FPM was definitely faster when using some simple PHP scripts to test against. Oddly we haven't noticed such a speed increase when benchmarking a Zend Framework based app, but that might be down to application oddities rather than anything else (more work/investigation needed here!).
Hope this is helpful.
James
From our experience if you wish to serve any kind of PHP apps with
internationalization using the popular GNU gettext system ( and right
now there are many of these) then you must use a non-threaded webserver
engine since GNU gettext library is not yet thread-safe (because GNU
gettext process environment variables can be set by any thread which
will drive the underlying GNU gettext library and these would affect
every thread in the process).
If you do not care about internationalization or using the most popular
system for translations, GNU gettext, then you can choose any webserver
engine type, threaded or non-threaded that your application will support.
Personally, I would never run a threaded engine in production.
Cross-thread contamination problems are most difficult to track down.
And I prefer to have complete isolation between connections which makes
it much simpler to track down problems. The so far tiny difference in
performance is outweighed by the isolation and debugging efficiencies
obtaining using a non-threaded webserver engine.
-Gerry
Hi All,
I have a few questions about the performance of PHP web applications under
load and I would appreciate if there is anyone that would like to share
their experiences in terms of any benchmarks or observations.Background Information
In multi-process environments, such as FastCGI, Apache Prefork MPM etc, PHP
needs to execute the MINIT and MSHUTDOWN functions for all loaded extensions
on every request.In a multi-threaded environment, such as Apache Worker MPM, with Zend Thread
Safety is enabled,
PHP only needs to execute MINIT and MSHUTDOWN functions once for each
extension and not each time a new thread is created to serve a request.It is also more expensive to create new processes than to create new
threads.In one-on-one comparisons between scripts executed only once in ZTS mode and
scripts executed once in non-ZTS mode,
I noticed that the one in non-ZTS mode was slightly faster and this seems to
be the main reason why most people go with the non-ZTS enabled setups.
But the reason for this slight difference in speed is because of the
differences in the data structure for globals for ZTS and non-ZTS modes.Other reasons people have cited for going with non-threaded setups include
stability which I guess we should not really be concerned about if
non-threadsafe extensions are excluded.Since it is generally more expensive to create new processes than new
threads, I believe that under high load, php in ZTS mode (multi-threaded
environment) will perform better than an identical setup in NTS mode
(multi-process).Problem
I noticed that Zend Server is using PHP in FastCGI mode (multi-process NTS)
and I am contemplating setting up apache in worker mode (threaded mode) and
compiling php in ZTS mode instead.Has anyone performed any load tests benchmarks comparing the two setups
(Multi-Process vs Multi-Threaded)?Are there PHP extensions that cause issues in threaded environments that I
should avoid?Are there any internals information or any other reasons why I should choose
ZTS over NTS or vice versa?Any useful feedback will be highly appreciated.
Thanks.
Hi,
I have spent a lot of time last year measuring php performance on
multi-threaded vs single threaded fastcgi.
I had used iplanet web server (instead of apache) for my measurement. Out of
the box single threaded php apps were very close (better) than multi-threaded
versions but when we started optimizing php for multi-threaded environment,
overall results were extremely positive (>35% faster than single threaded php
for an ecommerce apps). There is a lot of scope of improving multi-threaded
php. Some of the areas we looked at are:
- memory management
- file operations (caching stats call etc.)
- Session data caching (memsession php plugin)
- Removing TSRMLS_FETCH for emalloc/efree
- Reduce malloc and replace with emalloc in various php code paths.
- Pre-compute hash values of string constants at init-time rather than
when processing a request. - APC enhancement for multithreaded PHP apps.
- Using MPSS heap inside web server.
As far as multithreaded apps in production is concerned, entire java land runs
inside multithreaded servers and runs very nicely. php however has never been
optimized for multi-threaded web servers much so it runs lot nicer in single
threaded fastcgi environments.
Regards,
Basant.
From our experience if you wish to serve any kind of PHP apps with
internationalization using the popular GNU gettext system ( and right
now there are many of these) then you must use a non-threaded webserver
engine since GNU gettext library is not yet thread-safe (because GNU
gettext process environment variables can be set by any thread which
will drive the underlying GNU gettext library and these would affect
every thread in the process).If you do not care about internationalization or using the most popular
system for translations, GNU gettext, then you can choose any webserver
engine type, threaded or non-threaded that your application will support.Personally, I would never run a threaded engine in production.
Cross-thread contamination problems are most difficult to track down.
And I prefer to have complete isolation between connections which makes
it much simpler to track down problems. The so far tiny difference in
performance is outweighed by the isolation and debugging efficiencies
obtaining using a non-threaded webserver engine.-Gerry
Hi All,
I have a few questions about the performance of PHP web applications under
load and I would appreciate if there is anyone that would like to share
their experiences in terms of any benchmarks or observations.Background Information
In multi-process environments, such as FastCGI, Apache Prefork MPM etc, PHP
needs to execute the MINIT and MSHUTDOWN functions for all loaded extensions
on every request.In a multi-threaded environment, such as Apache Worker MPM, with Zend Thread
Safety is enabled,
PHP only needs to execute MINIT and MSHUTDOWN functions once for each
extension and not each time a new thread is created to serve a request.It is also more expensive to create new processes than to create new
threads.In one-on-one comparisons between scripts executed only once in ZTS mode and
scripts executed once in non-ZTS mode,
I noticed that the one in non-ZTS mode was slightly faster and this seems to
be the main reason why most people go with the non-ZTS enabled setups.
But the reason for this slight difference in speed is because of the
differences in the data structure for globals for ZTS and non-ZTS modes.Other reasons people have cited for going with non-threaded setups include
stability which I guess we should not really be concerned about if
non-threadsafe extensions are excluded.Since it is generally more expensive to create new processes than new
threads, I believe that under high load, php in ZTS mode (multi-threaded
environment) will perform better than an identical setup in NTS mode
(multi-process).Problem
I noticed that Zend Server is using PHP in FastCGI mode (multi-process NTS)
and I am contemplating setting up apache in worker mode (threaded mode) and
compiling php in ZTS mode instead.Has anyone performed any load tests benchmarks comparing the two setups
(Multi-Process vs Multi-Threaded)?Are there PHP extensions that cause issues in threaded environments that I
should avoid?Are there any internals information or any other reasons why I should choose
ZTS over NTS or vice versa?Any useful feedback will be highly appreciated.
Thanks.
"Israel Ekpo" israelekpo@gmail.com wrote in message
news:AANLkTi=ixWQkKovKYuLuQckDvkLQY2nYEyG6PJfZAn-G@mail.gmail.com...
In multi-process environments, such as FastCGI, Apache Prefork MPM etc,
PHP
needs to execute the MINIT and MSHUTDOWN functions for all loaded
extensions
on every request.
You're not correct here. A process can handle quite a lot of requests and
MINIT/MSHUTDOWN is executed only once.
So the MINIT/MSHUTDOWN overhead is negletable.
It is also more expensive to create new processes than to create new
threads.
Correct, but it's rarely needed to create them in both cases. So expense of
creation plays almost no role.
What plays role is switching the context when some overlapping requests are
processed. With thread it's less expensive.
But still, switching is a huge overhead when you run a server with 1K or 10K
overlapping requests.
If you talk about 10 or 40 - there is almost no difference.
In one-on-one comparisons between scripts executed only once in ZTS mode
and
scripts executed once in non-ZTS mode,
I noticed that the one in non-ZTS mode was slightly faster
that's because in ZTS case all data is in thread-safe structures and there
is quite a big overhead accessing any field of the structures.
and this seems to
be the main reason why most people go with the non-ZTS enabled setups.
No. Php if we talk about php with all its extensions is not threadsafe at
all. Many of the extensions allocate static data and inherently
non-thread-safe.
But the reason for this slight difference in speed is because of the
differences in the data structure for globals for ZTS and non-ZTS modes.
correct.
Other reasons people have cited for going with non-threaded setups include
stability which I guess we should not really be concerned about if
non-threadsafe extensions are excluded.
Correct. But you never know which one is truly threadsafe.
I'd only say that it's safer to use extensions that do not depend on 3rd
party libraries at all, or at least
depend on libraries written with threadsafety in mind.
Has anyone performed any load tests benchmarks comparing the two setups
(Multi-Process vs Multi-Threaded)?
Could you please shed some light on what load volume you're talking about?
1, 10, 100, 1K, or10K of requests per second?
with a regular web site which is handling ~4-5K visitors a day, you can
hardly get more than 10-15 requests per second.
In this case you may want to get what so ever php and apache distributed
with your OS and do not spend you time on anything else.
If you foresee 10K requests per second, it's better not to use PHP and
especially not to use Apache at all.
-j
Well, I would say that if your problem is memory, you should consider
threads as they all share the same memory space in their process.
Apache's children can weight very heavy if PHP's been compiled to
support lots of extensions, you can happen with ~40/50Mb per process
which is very huge. Considerating 50 parallel processes eat up 2-3Gb
for example.
In threaded environment, the best thing you'll get is a lot of memory
savings. The impact on CPU time is roughtly the same that with
processes (Unix).
Beware of non thread safe extensions/libs ; they'll cause you brain
damage for sure.
J.Pauli
"Israel Ekpo" israelekpo@gmail.com wrote in message
news:AANLkTi=ixWQkKovKYuLuQckDvkLQY2nYEyG6PJfZAn-G@mail.gmail.com...In multi-process environments, such as FastCGI, Apache Prefork MPM etc,
PHP
needs to execute the MINIT and MSHUTDOWN functions for all loaded
extensions
on every request.You're not correct here. A process can handle quite a lot of requests and
MINIT/MSHUTDOWN is executed only once.
So the MINIT/MSHUTDOWN overhead is negletable.It is also more expensive to create new processes than to create new
threads.Correct, but it's rarely needed to create them in both cases. So expense of
creation plays almost no role.
What plays role is switching the context when some overlapping requests are
processed. With thread it's less expensive.
But still, switching is a huge overhead when you run a server with 1K or 10K
overlapping requests.
If you talk about 10 or 40 - there is almost no difference.In one-on-one comparisons between scripts executed only once in ZTS mode
and
scripts executed once in non-ZTS mode,
I noticed that the one in non-ZTS mode was slightly fasterthat's because in ZTS case all data is in thread-safe structures and there
is quite a big overhead accessing any field of the structures.and this seems to
be the main reason why most people go with the non-ZTS enabled setups.No. Php if we talk about php with all its extensions is not threadsafe at
all. Many of the extensions allocate static data and inherently
non-thread-safe.But the reason for this slight difference in speed is because of the
differences in the data structure for globals for ZTS and non-ZTS modes.correct.
Other reasons people have cited for going with non-threaded setups include
stability which I guess we should not really be concerned about if
non-threadsafe extensions are excluded.Correct. But you never know which one is truly threadsafe.
I'd only say that it's safer to use extensions that do not depend on 3rd
party libraries at all, or at least
depend on libraries written with threadsafety in mind.Has anyone performed any load tests benchmarks comparing the two setups
(Multi-Process vs Multi-Threaded)?Could you please shed some light on what load volume you're talking about?
1, 10, 100, 1K, or10K of requests per second?with a regular web site which is handling ~4-5K visitors a day, you can
hardly get more than 10-15 requests per second.
In this case you may want to get what so ever php and apache distributed
with your OS and do not spend you time on anything else.
If you foresee 10K requests per second, it's better not to use PHP and
especially not to use Apache at all.-j
2010/12/15 Julien Pauli jpauli@php.net
Well, I would say that if your problem is memory, you should consider
threads as they all share the same memory space in their process.Apache's children can weight very heavy if PHP's been compiled to
support lots of extensions, you can happen with ~40/50Mb per process
which is very huge. Considerating 50 parallel processes eat up 2-3Gb
for example.
Surely creating a fork of a 50MB process will not consume an
additional 50MB because of copy-on-write virtual memory? I would think
you would only see this growth in memory usage if the extensions
maintained a large payload of data that was being heavily modified in
each request, such as caches, but I expect they create their own
shared memory segments (I have yet to check the source of APC).
Jon
Well, I can't answer precisely about kernel fork() implementation and
possible copy on write mechanisms. May vary across systems.
Someone here could answer I suppose.
'top' on httpd process with a prefork mpm gives each child process
memory as a whole XxxMb process, but I don't know what kind of memory
top sees (and other tools such as 'free').
Anyway, even with a good kernel process COW, threaded systems tend to
be less memory hungry than equivalent forked systems.
APC uses shared segments with differents tools such as shm, mmap
etc... (chosen at compile time).
J.Pauli
2010/12/15 Julien Pauli jpauli@php.net
Well, I would say that if your problem is memory, you should consider
threads as they all share the same memory space in their process.Apache's children can weight very heavy if PHP's been compiled to
support lots of extensions, you can happen with ~40/50Mb per process
which is very huge. Considerating 50 parallel processes eat up 2-3Gb
for example.Surely creating a fork of a 50MB process will not consume an
additional 50MB because of copy-on-write virtual memory? I would think
you would only see this growth in memory usage if the extensions
maintained a large payload of data that was being heavily modified in
each request, such as caches, but I expect they create their own
shared memory segments (I have yet to check the source of APC).Jon
Well, I can't answer precisely about kernel fork() implementation and
possible copy on write mechanisms. May vary across systems.
Someone here could answer I suppose.'top' on httpd process with a prefork mpm gives each child process
memory as a whole XxxMb process, but I don't know what kind of memory
top sees (and other tools such as 'free').
Anyway, even with a good kernel process COW, threaded systems tend to
be less memory hungry than equivalent forked systems.APC uses shared segments with differents tools such as shm, mmap
etc... (chosen at compile time).J.Pauli
http://www.kernel.org/doc/man-pages/online/pages/man2/fork.2.html
http://www.kernel.org/doc/man-pages/online/pages/man2/fork.2.html
Under Linux, *fork*() is implemented using copy-on-write pages,
so the only
penalty that it incurs is the time and memory required to duplicate the
parent's page tables, and to create a unique task structure for
the child.
Imo if you create the threads or worker processes beforehand, there isn't
much difference between the two method in performance POV.
good slides on the fork vs threads:
http://samba.org/~tridge/talks/threads.pdf
so for me I would go with the prefork, because it's easier to maintain
(non-thread safe apps are hard to debug :/)
Tyrael
No. Php if we talk about php with all its extensions is not threadsafe
at
all. Many of the extensions allocate static data and inherently
non-thread-safe.
PHP is, if compiled with ZTS/TSRM, thread-safe. Some libraries used by
some extensions might not be thread safe, but basically all "usually"
used ones are thread-safe. While it is a bit complicated as some
libraries could either be compiled thread-safe or not or some might be
not thread-safe on specific systems ... but that's not PHP itself ;-)
johannes
No. Php if we talk about php with all its extensions is not threadsafe
at
all. Many of the extensions allocate static data and inherently
non-thread-safe.PHP is, if compiled with ZTS/TSRM, thread-safe. Some libraries used by
some extensions might not be thread safe, but basically all "usually"
used ones are thread-safe. While it is a bit complicated as some
libraries could either be compiled thread-safe or not or some might be
not thread-safe on specific systems ... but that's not PHP itself ;-)johannes
Dear Johannes,
I'm not sure why you repeated what I stated in my post. So I'm repeating it
after you too :)
Yes, php core is developed with threadsafe techniques in mind, some
extensions are safe too, and some extensions which are using 3rd party
libraries are definitely not safe.
The only thing I'd kindly ask you to pay more attention to is using
"usually" word together with "safe" in one sentence. In my opinion they
should never be used both if we talk about production servers, or at least
servers where crashes are not welcome.
Just to illustrate the issue with "usually", do you consider openssl, a
widely used php extension, as a "usually threadsafe" extension?
If you do, please take a look at this page
http://www.openssl.org/docs/crypto/threads.html and these words in
particular:
OpenSSL can safely be used in multi-threaded applications provided that at
least two callback functions are set, locking_function and threadid_func.
locking_function(int mode, int n, const char *file, int line) is needed to
perform locking on shared data structures. (Note that OpenSSL uses a number
of global data structures that will be implicitly shared whenever multiple
threads use OpenSSL.) Multi-threaded applications will crash at random if it
is not set
Do you think any locking function is implemented in openssl php extension?
-j
No. Php if we talk about php with all its extensions is not threadsafe
at
all. Many of the extensions allocate static data and inherently
non-thread-safe.PHP is, if compiled with ZTS/TSRM, thread-safe. Some libraries used by
some extensions might not be thread safe, but basically all "usually"
used ones are thread-safe. While it is a bit complicated as some
libraries could either be compiled thread-safe or not or some might be
not thread-safe on specific systems ... but that's not PHP itself ;-)johannes
Dear Johannes,
I'm not sure why you repeated what I stated in my post. So I'm repeating it
after you too :)
Yes, php core is developed with threadsafe techniques in mind, some
extensions are safe too, and some extensions which are using 3rd party
libraries are definitely not safe.The only thing I'd kindly ask you to pay more attention to is using
"usually" word together with "safe" in one sentence. In my opinion they
should never be used both if we talk about production servers, or at least
servers where crashes are not welcome.Just to illustrate the issue with "usually", do you consider openssl, a
widely used php extension, as a "usually threadsafe" extension?
If you do, please take a look at this page
http://www.openssl.org/docs/crypto/threads.html and these words in
particular:OpenSSL can safely be used in multi-threaded applications provided that at
least two callback functions are set, locking_function and threadid_func.
locking_function(int mode, int n, const char *file, int line) is needed to
perform locking on shared data structures. (Note that OpenSSL uses a number
of global data structures that will be implicitly shared whenever multiple
threads use OpenSSL.) Multi-threaded applications will crash at random if it
is not setDo you think any locking function is implemented in openssl php extension?
In PHP a SSL_CTX is per thread and is not shared across other threads so it isn't an issue. We don't need to implement any openssl locking functions.
An example of non-thread safe is gettext it relies on the locale which is per process and not per-thread.
PHP itself at the core is thread safe. As Johannes said most common modules are too.
- Scott
Hi!
An example of non-thread safe is gettext it relies on the locale which is per process and not per-thread.
PHP itself at the core is thread safe. As Johannes said most common modules are too.
ICU btw has some global stuff too. It's actually worse as it has one
global which is set depending on current locale and never changed even
if PHP process changes the locale (yes, ICU has dependency on system
locale, go figure).
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
"Stas Malyshev" wrote
Hi!
An example of non-thread safe is gettext it relies on the locale which is
per process and not per-thread.PHP itself at the core is thread safe. As Johannes said most common
modules are too.ICU btw has some global stuff too.
I think it's clear that having any global stuff does not necessarily make
the code thread-unsafe.
Problem happens only if data can be modified in one thread while another
thread may access it.
For example you can safely have a lot of "thread-unsafe" things in MINIT and
MSHUTDOWN functions of your extensions.
The only thing you must follow is to have everything thread-safe in the
exposed API and in RINIT/RSHUTDOWN and all functions called in them.
It's actually worse as it has one global which is set depending on current
locale and never changed even if PHP process changes the locale (yes, ICU
has dependency on system locale, go figure).
It's my only guess - this is because a correct sorting of words in some
languages requires such thing as decomposition and therefore it is
locale-specific, even though the words are written in unicode. See p2 in
Sorting http://en.wikipedia.org/wiki/German_alphabet and ligatures in
http://en.wikipedia.org/wiki/French_alphabet
In the other hand, you may want to check some js implementations (like the
one in KDE) they use ICU Lite and all necessary functions are implemented on
top of the tables, perhaps they do not depend on the system locale.
-j
Hi!
ICU btw has some global stuff too.
I think it's clear that having any global stuff does not necessarily make
the code thread-unsafe.
Oh, this one does. It's not crash-unsafe, just weird-bugs-unsafe.
It's my only guess - this is because a correct sorting of words in some
languages requires such thing as decomposition and therefore it is
locale-specific, even though the words are written in unicode. See p2 in
No, it has nothing to do with this. See:
http://bugs.icu-project.org/trac/ticket/6711
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
"Scott MacVicar" wrote in message:
Do you think any locking function is implemented in openssl php
extension?
In PHP a SSL_CTX is per thread and is not shared across other threads so
it isn't an issue. We don't need to implement any openssl locking
functions.
It does not matter whether you think the locking functions are needed or
not. It's matter what openssl developers think and what assumptions they did
when developed the library. As I see they expressed it pretty clear - some
globals are implicitly shared among threads and this alone may cause crashes
if locks are not used. Do you have any strong reason to believe they are
wrong? They didn't say that it's SSL_CTX is the global struct that will be
implicitly shared. Even if you're correct and SSL_CTX is "the global", why
would they need 32 locks synchronizing access to it?
An example of non-thread safe is gettext it relies on the locale which is
per process and not per-thread.
PHP itself at the core is thread safe. As Johannes said most common
modules are too.
Not only yet. Do you remember dl()
? It's still here and being enabled may
cause races.
Do you think chdir won't cause races?
-j