Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:40346 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 41126 invoked from network); 8 Sep 2008 16:39:53 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 8 Sep 2008 16:39:53 -0000 Authentication-Results: pb1.pair.com smtp.mail=mls@pooteeweet.org; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=mls@pooteeweet.org; sender-id=unknown Received-SPF: error (pb1.pair.com: domain pooteeweet.org from 88.198.8.16 cause and error) X-PHP-List-Original-Sender: mls@pooteeweet.org X-Host-Fingerprint: 88.198.8.16 bigtime.backendmedia.com Linux 2.6 Received: from [88.198.8.16] ([88.198.8.16:59433] helo=bigtime.backendmedia.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id B9/81-33249-75555C84 for ; Mon, 08 Sep 2008 12:39:52 -0400 Received: from localhost (unknown [127.0.0.1]) by bigtime.backendmedia.com (Postfix) with ESMTP id 200A5414405C; Mon, 8 Sep 2008 16:41:15 +0000 (UTC) X-Virus-Scanned: amavisd-new at backendmedia.com Received: from bigtime.backendmedia.com ([127.0.0.1]) by localhost (bigtime.backendmedia.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id OooJsy4r5qvQ; Mon, 8 Sep 2008 18:41:13 +0200 (CEST) Received: from [192.168.80.196] (unknown [195.226.16.50]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) (Authenticated sender: mls@pooteeweet.org) by bigtime.backendmedia.com (Postfix) with ESMTP id 1B7474144059; Mon, 8 Sep 2008 18:41:13 +0200 (CEST) Cc: PHP Developers Mailing List , Dmitry Stogov , stanislav Malyshev Message-ID: To: Greg Beaver In-Reply-To: <486FA5FB.1000300@php.net> Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Mime-Version: 1.0 (Apple Message framework v928.1) Date: Mon, 8 Sep 2008 18:39:20 +0200 References: <486FA5FB.1000300@php.net> X-Mailer: Apple Mail (2.928.1) Subject: Re: towards a 5.3 release From: mls@pooteeweet.org (Lukas Kahwe Smith) Hello All, There is no way around it given the feedback I am seeing about namespace usage in the wild, to warm up this old post again. This post and the additional commentary, especially about performance by Stas can be found in the archives at: http://marc.info/?l=php-internals&m=121527668606247 I think given the feedback from users, we really need to actually benchmark the performance slow down that Greg's proposed changes will bring. I also guess there are two types of users out there: 1) those that tend to always spice up their API's by wrapping pretty much all internal functionality (be if that the internal functionality has a procedural or an OO API). These are also the people that will have the more complex OO structures (deep inheritance). They also seem like the most heavy users of namespaces 2) those that keep their structures flat, use native API's directly and live in a mixed world of OO and procedural code So while we are assessing the impact its important to keep in mind which user type is going to be affected in what way. Furthermore I hope that some of the people that have build up a code base that uses namespaces will do this benchmarking, because otherwise we will hardly get any useful data. Even then of course the benchmarks must be taken with a grain of salt (as always). I am including the email from Greg at the bottom here, along with a reply from Stas (again read the archive to get the full story). Maybe if we think hard about this one (now that we know that its an important real world need), we can discover a solution that we did not see at first. On 05.07.2008, at 18:48, Greg Beaver wrote: >> 1) namespaces >> Here we need to make sure that the current state is now in a >> coherent state. I think Derick still has some issues [3] with the >> recent change by Greg [4], but even his criticism did not sound all >> to loud. So I think we are in a good state here? > > My recent changes aside, there are still some fubar issues with name > resolution, and there has been some offlist discussion of ways to > fix this that have not led to concrete onlist proposals yet. > > For those who don't know what I'm talking about, the question is how > to resolve an unqualified classname inside a namespace. i.e. this > code: > > a.php: > namespace Foo; > throw new Exception('is this Foo::Exception or ::Exception?'); > ?> > > Currently, the above code would throw ::Exception, because if a > namespaced class does not exist, internal classes are checked before > autoloading for performance reasons. However, if we execute this > code instead: > > b.php: > namespace Foo; > class Exception {} > include 'a.php'; > ?> > > then a.php would throw Foo::Exception. In other words, depending on > file inclusion order, classnames can change with current PHP > accepted practices. The solution to this is to use each namespaced > class explicitly: > > a2.php: > namespace Foo; > use Foo::Exception; > throw new Exception('this is Foo::Exception always'); > ?> > > However, all it takes is one forgotten "use" statement, and a very > subtle bug could be introduced later. > > Taking a step back, let's examine why autoload is not called before > checking internal classes - it is for performance reasons. However, > this performance enhancement causes unpredictable behavior *by > default* without explicit action. > > There is a simple solution, however. If one changes the name > resolution to this pseudo-code: > > 1) check Foo::Exception for existence > 2) if not found, try to autoload Foo::Exception > 3) if not found, check for ::Exception existence, userspace *or* > internal (addition of userspace check also fixes other problems > raised on-list) > 4) if not found, fail. > > This fixes the logic problem, and re-introduces the performance > slowdown for internal classes. FORTUNATELY there is a simple > solution to this, which is to "use" all global classes: > > namespace Foo; > use ::ArrayIterator; > $a = new ArrayIterator(array(1,2,3)); > ?> > > The above code works exactly the same as: > > namespace Foo; > $a = new ArrayIterator(array(1,2,3)); > ?> > > and short-circuits the name resolution to: > > 1) check ::ArrayIterator for existence > 2) if not found, fail. > > To summarize, we should scrap the "performance enhancement" that > introduces the potential for subtle and dangerous logic errors in > name resolution because it is still possible to achieve that > performance enhancement through one-time "use" of internal classnames. > > With these changes, namespace classname resolution will be 100% > deterministic regardless of file load order, it will still be > possible to override internal classnames with userspace classes, and > for the ultra-performance hungry, it is still easy to achieve faster > classname resolution for internal classes. Win-win. On 17.07.2008, at 19:57, Stanislav Malyshev wrote: >> In other words, with the current implementation, you can just do >> "use Foo::Exception;" and it works, but if you *forget* to do the >> use statement, you can get unpredictable behavior with no warning >> until your > > You get previctable behavior in all cases, there's no randomness in > the engine. > >> to "use ::Exception", then your code is simply slightly slower (1 >> extra call to autoload if it exists), but still works properly. It >> also tilts > > It's not slightly slower, it's *A LOT* slower - exhaustive search of > whole include path for *EACH* call mentioning internal class. That > means you have to declare *EACH* internal class - even if no clashes > ever existed - for *EACH* use. Basically, it's the same as always > using ::Class only implemented in a way that its disastrous effects > are hidden until you check performance of your code. Then you have > to go back and add use statement for each internal class in each of > your files. Lot's of fun that would be. regards, Lukas Kahwe Smith mls@pooteeweet.org