Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:107969 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 85662 invoked from network); 3 Jan 2020 11:30:47 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 3 Jan 2020 11:30:47 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 81D851804A8 for ; Fri, 3 Jan 2020 01:34:53 -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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS 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-lf1-f46.google.com (mail-lf1-f46.google.com [209.85.167.46]) (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 01:34:52 -0800 (PST) Received: by mail-lf1-f46.google.com with SMTP id m30so31513631lfp.8 for ; Fri, 03 Jan 2020 01:34:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=3DttV4xLkIxZWtkM8pj9sFFjryUyRrzUTJqqMcHWW3c=; b=KfSV80Am4KbbZ1QbEDOmhOB+vLVlLyOPHzem/LoPMc+TCdDCYVio71caGmd46oh9q3 6HIGKbexGbDs8pGpYjgWVLjT6siBfQpkDbY5TqANqULdy/hxNjOV4XQSgczmImNGTt/P t8c0ufGWS7Ypf6QHpHHdHVe9Ob2XjH4wxQ8l1V09yQo3AAz1w33L4xDzD7/1iSSRxwo1 IM9GajYIaB5v4Ns6YD+bGvn0JrjtAfg9eHOuXxyuhKHTSn13s8oue2vLjW+vINeKA04f JR/02tfEUZEkEewwbRNOhV0pcVY1jhUwEdLf3IveVrY5pt/qesrmy8YG5aSP6/mPAN16 ierw== 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=3DttV4xLkIxZWtkM8pj9sFFjryUyRrzUTJqqMcHWW3c=; b=k4vVD6mPkHIO7/7F7dR1Na0RmvyUFE37hYy0epKnqYK8fnEu/+E4haWxBF27jtZrzj ouXTv190dVeVp0XqOAgoiocq65rNlnzCvQx5sm1SRLPKTntyGIIkInZZGBPg87J9ZlEO USk3TYdjZ6s4oYjIHqDHeLXpPt0Ebuv2+Lz51pOEx723DvdHhc/eSvr+TkVWBOAr4NSx WoNWVqcG3DwXTerJpzmvil8lwB2BFTBaVe+EVIPmAgFwNTfrzlmlSknklEq8dwPqtiEA OEipP1L/ndtsZVcGif/0qcU/hQhxZLYDIVwS0yw7ek7HxlP//o5sF2vdd0CYsxKD3oid tRDQ== X-Gm-Message-State: APjAAAV+EXVrZHHPxXobNQ3aEAfDjYoDaNqEdxOkFlavkIbIr4qQzHXv cibF1RanQInJ0a/tdTdvdgQAiaYgN3jpIeYwccjhvemXHEs= X-Google-Smtp-Source: APXvYqx3QKFTOp2IAGqHBduQ4tgtkDpQVyXQx/Xg/zN+NWHJZ0Q/EId6b3gcCWFrTqQtEjzskMvw5HnP3OxkaP7fdnc= X-Received: by 2002:a19:6d13:: with SMTP id i19mr50418638lfc.6.1578044090683; Fri, 03 Jan 2020 01:34:50 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: Date: Fri, 3 Jan 2020 10:34:34 +0100 Message-ID: To: tyson andre Cc: "internals@lists.php.net" Content-Type: multipart/alternative; boundary="00000000000077165b059b390584" Subject: Re: [PHP-DEV] Autoloading functions/consts without a performance impact From: nikita.ppv@gmail.com (Nikita Popov) --00000000000077165b059b390584 Content-Type: text/plain; charset="UTF-8" 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 --00000000000077165b059b390584--