On 19/02/13 09:36, Terry Ellison wrote:
The point that this thread highlights is that apps developers /
administrators at both ends of the scale -- the enterprise and the
shared service user -- normally have little say over the
infrastructure architecture on which their application runs. In both
these cases the infrastructure will be hosting 100s if not 1000s of
apps, and the environment cannot be tailored to any one app. So
issues like storage architecture and security architecture (e.g.
UID-based enforcement of app separation) are a given as NFRs
(non-functional requirements). Use of NFS with server / storage
separation is still a standard implementation design pattern, when
enterprises require simple-to-manage scalability on these tiers. We
aren't going to change this, and neither will the O/P.
Surely PHP will achieve better penetration and the greater acceptance
if it can offer more robust performance in this sort of environment?
Sure, but then you can go with something like Redis.
But, again, if you go back to the original question, this has nothing to
do with often-changing data in a couple of PHP include files:
We have several Apache 2.2 / PHP 5.4 / APC 3.1.13 servers all serving
mostly PHP over NFS (we have separate servers for static content)."
So they are serving up all their PHP over NFS for some reason.
Brendon,
Just to follow up with a bit more detail, apart from the obvious NFS
tuning with things like the actimeo mount parameters, you can get a
better idea of what is going on if you use a local copy of one of your
apps running under a local linux apache server. This is an example from
my Ubuntu laptop, but it works just as well on a test VM if you still
use WinXX on your PC.
trace_wget () {
sleep 1
coproc sudo strace -p $(ps -C apache2 --no-headers -o pid) -tt -o
/tmp/strace$1.log
sleep 1; ST_PID=$(ps -C strace --no-headers -o pid)
wget "http://localhost/$2" -O /dev/null -o /dev/null
sleep 2; sudo kill $ST_PID
}
# start Apache in debug mode
sudo service apache2 stop
sudo bash -c ". /etc/apache2/envvars; coproc apache2 -X"
# trace three gets
trace_wget 0 phpinfo.php
trace_wget 1 mwiki/index.php?title=Main_Page
trace_wget 2 mwiki/index.php?title=Main_Page
#restart normally
sudo service apache2 stop
sudo service apache2 start
sudo chmod 777 /tmp/strace?.log
grep -c "open(" /tmp/strace?.log
grep -c "stat(" /tmp/strace?.log
The first get is just to load and prime the mod_php5 thread (Ubuntu has
a crazy localtime implementation), the second loads and compiles the PHP
MediaWiki modules needed to render a page, the third repeats this now
fully cached in ACP. In this case,
we have:
open() fstat()/lstat()
/tmp/strace1.log 108 650 (Priming the APC cache)
/tmp/strace2.log 27 209 (Using the APC cache)
So APC *does* materially reduce the I/O calls, and (if you look at the
traces) it removes most of the mmaps and compilation. The MWiki
autoloader uses require() to load classes but in the code as a whole the
most common method of loading modules is require_once() (414 uses as
opposed to 44 in total of the other include or require functions) and as
I said in my previous post, this I/O is avoidable by recoding the
ZEND_INCLUDE_OR_EVAL hander to work cooperatively with the opcode cache
when present.
Note that even when the cache does this, it still can't optimize coding
patterns like:
if ( file_exists( "$IP/AdminSettings.php" ) ) {
require( "$IP/AdminSettings.php" );
}
and IIRC mwiki does 4 of these on a page render. Here a pattern based
on (@include($file) == 1) is more cache-friendly.
Now this isn't a material performance issue when the code tree is
mounted on local storage (as is invariably the case for a developer test
configuration) as the stat / open overhead of a pre-(file) cached file
is microseconds, but it is material on scalable production
infrastructure which uses network attached NFS or NTFS file systems.
So in summary, this is largely avoidable but unfortunately I don't think
that we can persuade the dev team to address this issue, even if I gave
them the solution as a patch :-(
Regards
Terry Ellison