PHP RFC: Deprecate ticks
- Date: 2021-05-11
- Author: Nikita Popov email@example.com
- Status: Withdrawn
- Target Version: PHP 8.1
- Implementation: https://github.com/php/php-src/pull/6967
- Discussion: https://externals.io/message/114368
Ticks allow running a function “for every N low-level tickable statements”. Historically, they have been used for handling pcntl signals. However, they have outlived their usefulness and this RFC proposes to deprecate and remove them.
Prior to PHP 7.0,
declare(ticks=N) was infectious, in that it also affected any files included after the file where
declare(ticks) was used. This violated the
declare() contract, which scopes behavior changes to a single file or block, and was fixed in PHP 7.0. Now ticks only affect the file where they are declared in. However, this change has also made ticks largely useless: Most uses of ticks need the entire application to be instrumented with ticks, including library code you do not own. To make ticks even marginally useful, we'd have to move them from a declare to an ini setting.
The second issue with ticks is that they have a large performance overhead: They work by inserting an additional
ZEND_TICKS instruction for each statement, which will execute all registered tick functions. Even for trivial tick functions, this adds a lot of overhead.
The main use-case for ticks prior to PHP 7.1 were pcntl signals: As it is unsafe to run PHP code from a signal handler, handling of signals needs to be delayed until it is safe to do so. This can either be done with manual calls to
pcntl_signal_dispatch(), or automatically. Prior to PHP 7.1, the only automated mechanism were ticks, which would run
pcntl_signal_dispatch() as a tick function. Since PHP 7.1, async signals can be used instead, enabled through
Async signals work by setting a VM interrupt flag whenever a signal is received, which will be handled at the next VM interrupt check. This means that async signals do not impose any additional cost, beyond what is always paid to handle timeouts.
In PHP 8.1, using
declare(ticks=N) will generate a compile-time deprecation warning. The
unregister_tick_function() functions will be marked as deprecated and issue a deprecation warning when called.
In PHP 9.0, using
declare(ticks=N) will generate a compile-time error, and the
unregister_tick_function() functions will be removed.
Backward Incompatible Changes
The removal of the ticks mechanism is expected to have limited impact. The primary user of ticks were pcntl signals, and these are handled through async signals nowadays.
It is possible to use ticks to instrument all code by overriding PHP's file stream wrapper and rewriting all included files to add the
declare(ticks=N) directive. Apparently, there are people who use such an approach to monitor performance and memory usage of code.