Re: Comments about PHPTAL package proposal?

From: Date: Sun, 19 Apr 2009 21:15:14 +0000
Subject: Re: Comments about PHPTAL package proposal?
References: 1 2 3 4 5  Groups: php.pear.dev 
Request: Send a blank email to pear-dev+get-51762@lists.php.net to get a copy of this message
Kornel Lesiński wrote: > On 19.04.2009, at 17:56, Greg Beaver wrote: > >>> This is needed to avoid mix-up of files from PEAR and other >>> installations of PHPTAL, e.g.: >>> >>> include "my/framework/libs/PHPTAL.php"; >>> >>> won't work properly without enforced path prefix. There's same problem >>> when running test suite. Does PEAR have solution to this? >> >> Yes. Look at how phpDocumentor handles this. You provide a stub file >> that modifies include_path which other installations then use. > > phpDocumentor does: >> set_include_path(get_include_path() . PATH_SEPARATOR . >> dirname(dirname(__FILE__))); > > which doesn't solve the problem - if PEAR dir is somewhere in the > path, it will still be used instead of specified directory. > > And adding of directories earlier in include_path is unsafe - e.g. > applications having "config.php" could accidentally include PEAR's > Config package on case-insensitive filesystem (I have run into this > problem myself :) I have not looked at PHPTAL's code directly, but there are definitely ways to solve this by requiring users outside of PEAR to use a bootstrap file. One very, very important thing is to make certain all of the phptal files are in a subdirectory, thus the "config.php" problem simply won't exist, it will be "PHPTAL/config.php" (for instance). >> Incidentally, it is never wise to use constructs like: >> >> include CONSTNAME . '/path/to/blah.php'; >> >> because opcode caches will never cache your code at compile-time, as the >> path cannot be safely resolved until run-time. It makes your code >> intrinsically slower even with an opcode cache. > > I've tested this with APC and it seems to work fine (APC's stats > report hits for these files). Because include_path can be changed > anytime, "constant" paths aren't constant either. > > One more reason why I like PHPTAL_DIR prefix is that it's an absolute > directory and PHP doesn't need to stat() directories in include_path > to load these files. > As far as I understood, this was recommended by Rasmus in his > Drupalcon keynote (http://www.archive.org/details/simple_is_hard) To be honest, I was very skeptical of this claim, having talked in some detail with Rasmus when we were designing the standards for PEAR2, and so I watched the presentation, and am afraid to say I disagree with your interpretation of his recommendations. Rasmus talks about the high number of stats generated by the sample twitter-like code. This code uses DB_DataObject, which has (as all PEAR does) require_once. As Rasmus says "the real path is when we have a realpath cache miss" which means if your include_path is ".:/usr/local/lib/php", the penalty can be 10-20% over "/usr/local/lib/php:." as include_path - with no code changes. He also said that if you are indeed including relative to the current directory, it is better to use include "./relativepath.php" because PHP treats this as an absolute path, and performs many fewer stats. This, however, is a performance recommendation that should only be followed if you always know what getcwd() will be (which we don't for PEAR or any other library package). The other problem was that the _once in require_once causes realpath to be used, whereas this is not needed for require. To clarify my point, this is the order of performance without opcode cache (as tested by a synthetic benchmark using siege, and verified by Stas Malyshev at Zend labs): 1) include '/full/path/to/file.php'; 2) include_once '/full/path/to/file.php'; 3) include 'relativepath.php'; 4) include_once 'relativepath.php'; 5) include CONSTANT . '/relativepath.php'; 6) __autoload() with include (no _once) 7) include Blah_Loader::Load('ClassName'); with opcode cache, the speed is similar, but the ratios change. __autoload performance degraded (for instance), and the include with full path performance went through the roof. Also, include and require are basically interchangeable in performance, with include being ever-so-slightly faster. Why is include CONSTANT . '/relativepath.php' slower? The difference is not whether APC caches, but when. With a static include statement, APC can figure out at compile-time where the file is, and never needs to hit the executor in some situations. What this means is that APC can turn the opcodes for the include into NOPs, which is much faster than the opcodes it takes to replace CONSTANT with its value, concatenate with '/relativepath.php' and then pass to the include opcode, which calls compile, which invokes APC (finally). So, it may not seem like it, but require_once is indeed faster in almost any situation except for a poor include_path setup. By the way, these problems literally do not exist in PEAR2. Dependent file loading is moved to where it belongs - the application level. Those looking for convenience use __autoload(), and later if the application becomes performance-intensive, it is possible to move to faster methods of file loading such as including full path with __autoload() as a fallback. It also makes it possible to move a package like PHPTAL to a sub-directory and load it any way the application sees fit. Thanks, Greg

« previous php.pear.dev (#51762) next »