[php-src] PR #24198: Zend: Build the message of a persistent #[\Deprecated] once
| From: | ArtUkrainskiy | Date: | Thu, 08 Oct 2026 15:18:14 +0000 |
| Subject: | [php-src] PR #24198: Zend: Build the message of a persistent #[\Deprecated] once | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-39256@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/24198
Author: ArtUkrainskiy
First of the two steps in GH-24191.
Emitting the deprecation of an internal function constructs a
\Deprecated object on
every call to read its message and since:
zend_get_attribute_object(), the constructor through zend_call_function()
with named arguments, two property writes, two reads, destruction — about 2,900 of the 5,000
instructions a deprecated call costs, paid whether or not E_DEPRECATED is reported. The
arguments of a persistent attribute are stub literals, so the suffix they produce never changes.
This builds it on the first use and keeps it in the attribute as an immutable persistent string. The
attribute is shared by every copy of the function (closures, reflection) and by every thread, so the
store is a compare-and-swap and the string is freed with the attribute in attr_free();
readers take an acquire load. #[\NoDiscard] gets the same treatment. Attributes of user
code keep building the object: their arguments may be constant expressions and their structs live in
opcache's shared memory.
ReflectionProperty::setAccessible(): 5,010 → 1,807 instructions per call, reported or
filtered alike; the message is byte for byte the same (test added, covers repeated calls, a closure,
reflection and an error handler).
Checked on a debug ZTS build with --enable-werror: Zend/tests, ext/reflection,
ext/date, ext/opcache (including with opcache.file_cache) pass. Measurements and how
the cache behaves per SAPI: https://github.com/ArtUkrainskiy/php-src-bench/tree/main/reports/deprecation-cost