Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:40479 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 75226 invoked from network); 12 Sep 2008 04:41:15 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 12 Sep 2008 04:41:15 -0000 Authentication-Results: pb1.pair.com header.from=greg@chiaraquartet.net; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=greg@chiaraquartet.net; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain chiaraquartet.net from 208.83.222.18 cause and error) X-PHP-List-Original-Sender: greg@chiaraquartet.net X-Host-Fingerprint: 208.83.222.18 unknown Linux 2.6 Received: from [208.83.222.18] ([208.83.222.18:51278] helo=mail.bluga.net) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 80/C3-49770-AE2F9C84 for ; Fri, 12 Sep 2008 00:41:15 -0400 Received: from mail.bluga.net (localhost.localdomain [127.0.0.1]) by mail.bluga.net (Postfix) with ESMTP id EF08CC0E2F5; Thu, 11 Sep 2008 21:40:24 -0700 (MST) Received: from [192.168.0.106] (CPE-76-84-4-101.neb.res.rr.com [76.84.4.101]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.bluga.net (Postfix) with ESMTP id 834E1C0E2F4; Thu, 11 Sep 2008 21:40:24 -0700 (MST) Message-ID: <48C9F2F6.4080007@chiaraquartet.net> Date: Thu, 11 Sep 2008 23:41:26 -0500 User-Agent: Thunderbird 2.0.0.16 (X11/20080724) MIME-Version: 1.0 To: Stanislav Malyshev CC: internals@lists.php.net References: <48C59D5C.4050507@chiaraquartet.net> <48C5A909.4030502@zend.com> <48C602D5.6020704@chiaraquartet.net> <48C6A6AA.7050003@zend.com> In-Reply-To: <48C6A6AA.7050003@zend.com> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Virus-Scanned: ClamAV using ClamSMTP Subject: Re: [PATCH] Re: [PHP-DEV] namespace examples (solving name resolutionorder issues) From: greg@chiaraquartet.net (Gregory Beaver) Hi, This is the 2nd of two exchanges that occurred off-list that Stas and I would like to put back on-list. Greg === Stanislav Malyshev wrote: > > Hi! > > >> >> Basically, the patch does 2 things >> >> >> >> 1) resolution order is changed to: >> >> >> >> foo.php: >> >> $a = new foo(); >> >> a) does namespace::foo class exist? >> >> b) try to autoload namespace::foo >> >> c) try to locate internal class ::foo >> >> >> >> 2) if internal class ::foo is found, then cache this information so that >> >> if another reference to the foo class occurs in foo.php, resolution >> >> short circuits to: >> >> a) use internal class ::foo >> >> >> >> This second point is why the slowdown went from ridiculous to slight. > > > > OK, now I understand better what it does, thanks. Do I understand > > right that the caching is in runtime, when the class access opcode is > > executed (since you couldn't autoload in compile time)? If so, how > > long the cache entry is kept there? I.e. if I have execution path that > > goes to file A, then B, then A again, then C, then B, etc. and then > > unroll the stack back - do I store all results for second entrance > > into A? Is it per-op-array (since we don't have per-file data > > structure AFAIK)? What happens if include path (or autoloader) > > changes, so that the class name that could not be loaded before can be > > loaded now - e.g. application adds plugin definitions, etc. - will it > > be ensured that autoloading is never attempted again for the same > > class? What happens if somebody loads that namespace::foo class > > manually (with require) - will the old resolution hold or the new one > > apply? > > > > Also I note that even if the cache stores all resolutions for all > > internal classes times all namespaces, it will still require at least > > one exhaustive autoload search per internal class per op-array - or > > per file, if you somehow find a way to store cache per-file in > > runtime, and these can not be eliminated with bytecode caching, unlike > > all other filesystem accesses. Hi, The caching is at runtime. Basically, it's in executor_globals, and so is not linked to any opcode array (I couldn't figure out any other globally accessible storage location). It works like an associative array. If file X.php loads XMLReader in namespace namespacename, it creates this entry: array( 'X.php\0namespacename::XMLReader' => {class entry for XMLReader} ); So that the next time we reach X.php and the XMLReader class, it sees this entry, and does not attempt autoload. As for your questions about include_path/autoload, I had not added this to the patch, but the easy solution is to clean the hash on include_path change, or autoload change. I assume this code would break with the patch: sneakyreader.php: main.php: Whereas with the current behavior, it would instead instantiate foo::XMLReader on the second access. However, this is definitely a wtf situation - the exact same looking line of code would load a different class name entirely depending on what was included. The cache does not eliminate the first autoload per-file. I'm sure there are other issues to work out, but this should give a better idea of what I am trying to do. As for your question of whether to simply error out if foo::XMLReader doesn't exist (in the main.php example above), this also would be acceptable for classes, but not for functions, as the ratio of user-defined to internal functions in any source code example is 1:many, many. However, we don't autoload functions or constants, so load ordr is an absolute, much as it was for classes in PHP 4 before autoload was introduced. It is not an easy problem to solve, but we do need to solve it prior to the next release. Should we take this back on-list? Greg