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

Reply via email to