Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:107970 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 4827 invoked from network); 3 Jan 2020 13:18:37 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 3 Jan 2020 13:18:37 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id CF20C1804F8 for ; Fri, 3 Jan 2020 03:22:41 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2, SPF_HELO_NONE,SPF_NONE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-il1-f170.google.com (mail-il1-f170.google.com [209.85.166.170]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 3 Jan 2020 03:22:41 -0800 (PST) Received: by mail-il1-f170.google.com with SMTP id x5so36364116ila.6 for ; Fri, 03 Jan 2020 03:22:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mindplay-dk.20150623.gappssmtp.com; s=20150623; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=7F+3O0PDSWbIff8HSDHip+v+kOFs/lzNRI9asjlm8Y8=; b=rVSPTklm3UoIMHMlgRWMbj3V5WGNCAqrcC0lG4hCK84kPGsDHSIQSuZW0clHeURy90 V2+pOADsc+Mfg+XXKtJjekMvMjN8VKvfKDK/mkhLHt9ZoRBY7dOtDKoIg++Tz082Cx18 1BwR/2pD7aOQkjQsremYpXoCcapl90IVsZPBix9fGko/n+dfH5+KITV4vTLae76qdApr 4iZC+AG6n1mwTus1eidBthAyerx1AJoUVTIh4dvl7xi6Svb6egmozWEZ5tX8UkpzBvt1 OydISo1dTVx7GSqyOumVO94Z9npfwRPgAefjcuTTiyyo7ABbGcwd39fhHaq7Dh9n9OhU kh+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=7F+3O0PDSWbIff8HSDHip+v+kOFs/lzNRI9asjlm8Y8=; b=oaFnPQo8kaH1/AL2uhPpKDZjJ2qmcOgZ+X6Xaniew4HFSB5uDoV/dc1v2x0J2Y0vZn iWiQhhCeN2owHhRxvgeibCeynaDAI9o44rA8hWzN8pd6yKBgUVF3pFk4va+eJ4LhJhxk PSG3M6bU8k1W++wrO3OW3Q7hMLcOEb6Il13YFdCYNRDFBsp3Hwh1WImKjDsfy0DMQ3q+ 4mpj7OHCkX69JpTJqDVQ6KAyAJHtysf90DdwQVY7pf2sobWJAmcTewIeUIE01jOMtaxY V0pUdoe1VpfLy8AKle7yHG5sF2jjFTMvs5PqSnCF7HJQ1zhQI6DPCj0HCqva55uVWbwZ n0Fw== X-Gm-Message-State: APjAAAW93J+L5c02hezeLPenaKfqMniXuaSukWbdmBZsK5GNIRNz8fMy LFqha9QHT6x37QU8/xtDekrjH3z9DYTKYHdAj5zlug== X-Google-Smtp-Source: APXvYqzfxxEGeQn0aa+iTm8jMeJ/4pB5GpT0FoYkQ5FBp9R21/vYz86Ht6wYHhGtDPlQALXqJpHxZUa1oTteROLRB6g= X-Received: by 2002:a92:1648:: with SMTP id r69mr76950567ill.43.1578050558977; Fri, 03 Jan 2020 03:22:38 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: Date: Fri, 3 Jan 2020 12:22:29 +0100 Message-ID: To: Nikita Popov Cc: tyson andre , "internals@lists.php.net" Content-Type: multipart/alternative; boundary="000000000000018243059b3a87da" Subject: Re: [PHP-DEV] Autoloading functions/consts without a performance impact From: rasmus@mindplay.dk (Rasmus Schultz) --000000000000018243059b3a87da Content-Type: text/plain; charset="UTF-8" On Fri, Jan 3, 2020 at 10:35 AM Nikita Popov wrote: > On Fri, Jan 3, 2020 at 2:51 AM tyson andre > wrote: > > > After a quick search, it turns out I've mostly reinvented > > https://wiki.php.net/rfc/autofunc which I hadn't remembered. > > The `spl_autoload_*()` changes it mentions is what I had in mind > > > > There's been changes to php since then, it's been 7 years, > > and this adds thoughts on some implementation details. > > > > It's possible to support function / const autoloading > > in a way that keeps existing performance. > > Some of the objections at the time no longer apply. > > > > - `SOME_CONSTANT` no longer falls back to the literal string in php 8. > > It throws an Error. > > - APC (used by some implementations) is no longer supported. > > - Many of the objections were against the available implementations > > based on `function __autoload()`, not the concept of autoloading. > > > > https://www.mail-archive.com/internals@lists.php.net/msg52307.html > > - There wasn't much traction from leads for the concept > > or a Proof of Concept to vote on for that RFC (I think). > > > > What if an ambiguous `function_name()` or const outside the global > > namespace would attempt to autoload functions in the global namespace > > if it would throw an Error, but not the current namespace? > > > > `function_exists()` or `defined()` would not autoload, > > to preserve the behavior/performance of current programs. > > Anything with the callable type hint (e.g. `array_map`) would also need > to > > be modified, > > but I think it already needs to do that for method arrays and > > 'MyClass::method'. > > > > - Same for global constants > > - That should avoid the performance hit - this autoloading would only be > > triggered > > when php would previously throw an Error or warning > > for undefined functions/constants. > > - This would also avoid the need to load polyfill files (e.g. mbstring) > > or test framework files when their functions/constants are unused. > > - One blocker for other autoload proposals > > seemed to be performance if I understood correctly > > (e.g. attempting to autoload NS\strlen() every time strlen was called). > > > > https://externals.io/message/54425#54616 and > > https://externals.io/message/54425#54655 > > detail this - choosing a different order of checks avoids the > > performance hit. > > - In addition to the RFC, changing the signatures to `defined(string > > $name, bool $autoload = false)` > > and `function_exists($name, bool $autoload = false)` > > might be useful ways to allow users to choose to autoload when checking > > for existence. > > > > And there'd have to be a hash map, flag, or other check > > to avoid recursion on the same constant/function. > > > > Background: A function call or constant usage is > > ambiguous if it could look for the function in two namespaces, > > as described by the rules documented in the below link. > > It's unambiguous if it ends up looking in only one namespace. > > > > https://www.php.net/manual/en/language.namespaces.rules.php > > The only type of ambiguous function call or global constant use is (7.): > > > > > 7. For unqualified names, > > > if no import rule applies and the name refers to a function or > > constant > > > and the code is outside the global namespace, the name is resolved > at > > runtime. > > > Assuming the code is in namespace A\B, here is how a call to > function > > foo() is resolved: > > > 1. It looks for a function from the current namespace: A\B\foo(). > > > 2. It tries to find and call the global function foo(). > > > > My approach should be in line with the current name resolution > > for unqualified names outside the global namespace. > > > > 1. It (first) looks for a function from the current namespace: A\B\foo(). > > 2. It (next) tries to find and call the global function foo(). > > 3. (Optional) NEW ADDITION: Next, if both functions were undefined, > > the autoloader(s) attempt to autoload the function A\B\foo() > > (and call it instead of throwing if found) before proceeding to step > > (4.) > > 4. NEW ADDITION: If both functions were undefined, > > the autoloader(s) attempt to autoload the global function foo() > > (and call it instead of throwing if found) before throwing an Error > > > > And for unambiguous calls, find and autoload the only name it has. > > > > The fact that one of the two possible functions gets cached by the php VM > > in CACHED_PTR > > (for the lifetime of the request) the first time the function is found > > in either namespace will remain unchanged with this proposal. > > > > I believe the problem here is this: The fact that the global function is > being cached, and continues to be cached when a namespaced function is > later defined, is a bug. See for example > https://bugs.php.net/bug.php?id=64346. We've never prioritized fixing this > issue, but implementing the proposed autoloading behavior would make fixing > it essentially impossible, as we certainly can't perform an autoloader > invocation on each call. > > Nikita > I will just briefly mention an alternative idea I've brought up before. (there's no RFC for this.) use function MyClass::myStaticFunction; myStaticFunction(); This would allow importing a static function and calling it just like a flat function. The way most people normally write code in PHP, they're favoring static functions over flat functions, since aggressively preloading flat functions (e.g. "file" in "composer.json") doesn't scale, and using manual include/require statements is clumsy and error-prone. (and not really possible with Composer.) Many existing PHP codebases already have "classes" that are really just "pseudo-namespaces" for collections of functions, so this approach takes into account the existing ecosystem. It also implicitly addresses autoloading, which would just automatically work with Composer (or any class auto-loader) with no further changes. It also bypasses any learning curve surrounding function name resolution rules, if this were to become more complex by adding more rules and details with regards to resolving and autoloading flat functions. Is there a really good reason to encourage the entire community to migrate all of their existing codebases from static classes to flat functions? Expecting Composer to add support for it. Expecting package vendors to list all function names in package metadata files, and so on. In many cases, migrating from static to flat functions also means migrating any constants from class constants to namespaced constants - so this likely leads down the rabbit hole to autoloading constants as well, and/or having to use some mix of class constants and flat functions which isn't very desirable. Is there any practical return on that investment? Static functions aren't really any different from flat functions. (if you're thinking "state", that's really up to the author - your flat functions could depend on global state just like a static function could depend on static properties...) Just my five cents on the matter :-) --000000000000018243059b3a87da--