Re: clarification on the performance of require_once and APC
| From: | Alexey Borzov | Date: | Sun, 26 Aug 2007 19:35:18 +0000 |
| Subject: | Re: clarification on the performance of require_once and APC | ||
| References: | 1 2 3 | Groups: | php.pear.dev |
| Request: | Send a blank email to pear-dev+get-47843@lists.php.net to get a copy of this message | ||
Hi,
Gregory Beaver wrote:
Sure. This code: s file1.php <?php require_once 'foo.php'; ?> file1.php <?php $driver = 'foo'; require_once $driver . '.php'; ?> is a simplistic example of an unconditional and conditional inclusion of the same file. The problem was when classes have cross-file inheritance relationships between unconditional and conditional inclusion, sometimes the same file was included in different ways on different iterations, resulting in erroneous caching of the class definition. This led to segmentation faults or worse, random fatal errors due to mis-defined classes. If you'd like, I can poke Gopal to find out more detail, but it is actually unsolvable as long as we have both top-level and conditional require_once.So these are deficiencies in a third party product that we want to work around. OK, what are the *other* third party products that we will treat the same way?
When I say clever design, I mean doing this kind of check for the driver inside MDB2: <?php (assuming we're in namespace PEAR2 and have imported PEAR2::MDB2::Exception as Exception) if (class_exists('MDB2::mysqli', true)) {OK, so we will have this clever check in all packages that should conditionally include code? Why not create a PEAR2_Loader class then rather than copy-and-paste?return true;} elseif (file_exists('PEAR2/MDB2/mysqli.php', true)) {require 'PEAR2/MDB2/mysqli.php'; return true;} elseif (file_exists(dirname(__FILE__) . '/MDB2/mysqli.php')) {require dirname(__FILE__) . '/MDB2/mysqli.php'; return true;} else {throw new Exception('Cannot locate mysqli driver - have youinstalled PEAR2_MDB2_mysqli package?'); } ?> It is my mistake (and a large one) that the language of the RFC does not currently allow this kind of design. require should probably be allowed as a fallback for loading dependencies if they don't exist, the purpose of the new design is to provide more flexibility, not to limit it.
I will think about better wording, and if you have any suggestions, please let us know.Of course the file shouldn't contain any require_once calls as it will just contain all the code. Let's enforce the "one package --- one file" rule: it will both improve performance and ease of use, since even the most clueless user won't have any problems understanding which file to include....which is not possible without munging if a file contains any unconditional top-level "require_once" statementsThe best performance is to be achieved by having a single include statement for each needed file in the entire application.Better yet performance can be achieved by putting everything into a single file. We should also consider stripping comments and whitespace from this file so that parser's job is easier if the user does not use a bytecode cache.
This of course nullifies the "PEAR2 should be easily relocatable" claim made here: http://wiki.pear.php.net/index.php/Pear2_requireAnd here I'd like to re-ask one of my questions. Currently people can run usage examples and tests right after they install the package. After the proposed changes are implemented will they have to mangle usage examples to make them run?No, and in fact if they do, then we need to change the proposal. I think one solution might be to relax the replacements restriction for documentation and tests files. The new language would read something like: replacements are forbidden in files that are intended to be used in production environment (role="php", role="data", role="www") but are encouraged in documentation examples and in tests in order to demonstrate proper usage out-of-the-box. In other words, by providing two examples and using an install-as tag, it becomes possible to provide examples for unzip-and-go and for pyrus-installed. [Note: these are spur-of-the-moment examples, I am sure better design could be thought of with more thought and experimentation by others] pyrus_example1.php <?php // if you installed this package using pyrus, this is the example for you // we are in docs/PEAR2_MDB2/unzip_example1.php set_include_path('@php_dir@'); require 'PEAR2/autoload.php'; function __autoload($class) {return PEAR2_autoload($class);} import PEAR2::MDB2; $db = MDB2::connect('mysqli://...'); ?>
Exactly here lies a problem. The distribution model you describe here is common for *applications*, while most of the stuff in PEAR is currently *libraries*. I am 99% sure this will be the case with PEAR2 as well. And this even not mentioning the fact that most current *nix users are more accustomed to some kind of package manager and most Windows users are accustomed to shiny graphical installers.First of all, these will not be scattered throughout the filesystem, they will be in the base directory. In other words: unzip PEAR2_Package.zip ls README* README.PEAR2_Package This will mean that the php_dir of pyrus will contain a README for each installed or unzipped package. Users who are unaccustomed to PEAR are not by definition stupid just as people accustomed to PEAR are not by definition smarter. They are simply used to an older distribution model that is like so: 1) download .zip or .tar.gz 2) extract 3) look for README or INSTALL file and read them both.I would like each package to have a top-level README.PackageName file, so that when it is installed or when it is unzipped, this file is easy to find. For instance: pyrus install PEAR2_PackageName PEAR2_PackageName installed into /full/path/to/pear2/ - read README.PEAR2_PackageName to get startedIf your target audience is the people who are unable to set up include_path then we have strong empirical evidence that they aren't reading the docs that are available now in a *single* place on PEAR's website. Do you honestly expect them to read those README files scattered throughout the file system?
As I remember it, include_path is an innovation that was introduced into PHP in order to support PEAR. Most users use direct inclusion or assume that they are simply including files relative to the current directory, without knowing that include_path often contains "."This "innovation" is available in most other programming languages. So people who are familiar with programming in general, should understand what "library path" is about.
Your contention that this proposal is designed to attract stupid people is a straw man argument - no one benefits from attracting stupid people. However, there are plenty of smart PHP developers who are simply not as familiar with include_path because they've never needed to know about it.My opinion is that solution to include_path problems is not getting rid of include_path, but educating people about include_path. Here is also my rant on how stupid package design decisions contribute to these problems: http://marc.info/?l=pear-dev&m=118474842223805&w=2 People who can be educated will read the docs, people who can't be educated would read neither the docs nor your proposed README files. You, being American, may also overlook another issue: while the manual can be (and even *is*) translated, most of the stuff installed alongside packages will only remain English.
All that the new proposal mandates is that we stop using top-level require_once. The rest is experimental solutions to doing things, and all possibilities should be explored until we find one that makes coding with PEAR2 packages just as easy as coding with PEAR packages.OK, the $100 question: if such a possibility is not found, will you consider dropping the proposal?
One obvious example of a process that would be far simpler without the problem of top-level require_once munging is the go-pear script. Currently, it has to do all kinds of non-obvious weird stuff to get things downloaded, and additionally is very difficult to read. If we remove all the require_once, go-pear could literally use the PEAR installer itself by cramming all of the needed files into a single file, and putting the installation script at the top of the file. This would even allow us to consider not using a phar archive for PEAR installation within PHP, but still supporting a single-file installation model.go-pear script is an edge case. I don't think the solution that makes it easier to do some pretty rare task while making it harder to perform most other tasks is a good one.