Skip to content

About

Reference scheduler extension for the PHP Async Core ABI. The C implementation of the scheduler hooks

Topics

Resources

Stars

7 stars

Watchers

1 watching

Forks

Repository files navigation

True Async logo True Async

CI License: BSD-3-Clause PHP 8.7-dev Status: early

True Async is coroutines for PHP as an ordinary PHP extension, the module true_async. It rebuilds TrueAsync to load into a PHP built from stock php-src plus the async RFCs, with no php-src patches of its own.

Status: early. The extension builds, loads and is tested in CI on Linux and Windows; coroutines come next. The work plan is dev/PLAN.md.


Table of Contents


Goals

  • No private core. Today's TrueAsync needs its own fork of php-src, so it cannot be installed into a distribution's PHP or through PIE. True Async uses only the public core APIs proposed upstream:

    A change it needs in the core goes to the RFC as a request, never into a patch shipped here.

  • The TrueAsync API. The classes, functions and behaviour of TrueAsync are kept: code and tests written for it run here. Where an RFC sets a stricter rule, the RFC wins, and the difference is recorded in dev/DECISIONS.md.

  • The reactor on the core's IO APIs. Waiting, timers and IO go through the core's php_io_queue: the Ring over ior where built, the Poll queue otherwise. No libuv.

  • Performance. Spawn, switch, suspend and await are measured against TrueAsync; a change on the hot path comes with its numbers.

  • Tests first. Each stage freezes its list of tests, ported from TrueAsync, before its code. Every run goes through debug and ASAN+UBSAN builds, and mutation testing checks that the tests catch broken code.

  • Linux and Windows. Every stage builds and runs its tests on both.


Architecture

flowchart TB
    app["PHP code<br/>Async\spawn, await, suspend, Coroutine"]

    subgraph ext["true_async extension"]
        sched["Scheduler<br/>coroutines, run queue, cancellation"]
        reactor["Reactor<br/>timers, idle wait"]
        provider["IO provider<br/>blocking PHP functions suspend the coroutine"]
        collector["Async object collector<br/>deadlocks, unreachable waits"]
    end

    subgraph core["php-src core with the RFCs"]
        sapi["Scheduler API<br/>21 slots, #22561"]
        hooks["IO hooks<br/>#23997"]
        queue["php_io_queue<br/>Ring (ior) or Poll"]
    end

    app --> sched
    sched -- registers --> sapi
    sched --> reactor
    reactor --> queue
    provider -- implements --> hooks
    provider --> queue
    collector -. walks the wait graph .-> sched
Loading

Roadmap

Progress 77% Current stage S8

Stage Progress Done
✓ S1 · Core branch async-core-io ██████████ 100 %
✓ S2 · Repository and test system ██████████ 100 %
✓ S3 · Scheduler on the scheduler API ██████████ 100 %
✓ S4 · Reactor on Poll, Poll additions and Ring ██████████ 100 %
✓ S5 · Futures, timeouts and combinators ██████████ 100 %
✓ S6 · IO hooks provider ██████████ 100 %
✓ S7 · Async object collector ██████████ 100 %
▶ S8 · Review checks and RFC change list █████████░ 88 %
S9 · Higher layers, one at a time █████████░ 93 %
✓ S10 · Beyond the RFCs ██████████ 100 %
S11 · Namespace Async renamed to TrueAsync ░░░░░░░░░░ 0 %
S13 · The provider from the request's start, after bukka's pipe refactor ░░░░░░░░░░ 0 %
✓ S14 · Health check fixes ██████████ 100 %
S15 · Test layers of S2 not built yet ░░░░░░░░░░ 0 %

Total: 77 %, the mean over 14 stages; a stage counts its closed steps in dev/PLAN.md. Generated by tools/roadmap.py.


The core

Until the RFCs are merged, the core is the php-src branch async-core-io: php-src master with the two proofs of concept merged, nothing else. dev/WORKFLOW.md pins its revision and gives its configure line.


Known limitations

Regular files are read and written on the thread. A fread() or fwrite() on a file holds every coroutine until it returns; a socket read does not. The core's Ring can run file IO in the background, but while a coroutine waits on a stream the core refuses that stream to every other coroutine with Error: Concurrent access to a stream. With files in the background, two coroutines writing one log file, or including from one phar, would fail; TrueAsync queues them on the handle instead. Files go to the background once the core queues such waits (dev/RFC-CHANGES.md 12). The same Error already meets two coroutines using one socket or pipe at once.


Build

Linux, against an installed core:

phpize
./configure --with-php-config=<core prefix>/bin/php-config --enable-true-async
make
php -d extension=modules/true_async.so -d true_async.enable=1 --ri true_async

true_async.enable (system INI, default 0) lets a PHP that loads the extension run another scheduler.

Windows: the repository goes into ext\true_async of the core tree and PHP is built with --enable-true-async; tools/windows/ does it with Debug_TS or Release_TS.

C sources follow .clang-format (the php-async configuration plus PHP macro rules): tools/format.sh rewrites them, tools/format.sh --check is what CI runs.


Tests

TRUE_ASYNC_CORE_SRC=<core checkout> tools/test.py --lane pocs-dbg   # pocs-asan, pocs-dbg-cov
tools/check-lists.py --reference <php-async checkout>
tools/mull.py --known-answer
Lane Build
pocs-dbg ZTS debug core, ZendMM on
pocs-asan ZTS debug core with ASAN + UBSAN, USE_ZEND_ALLOC=0
pocs-dbg-cov the debug lane with gcov; line coverage of src/
pocs-dbg-mull clang 18 with Mull, for mutation testing (tools/mull.py)
pocs-win Windows, the extension built inside the core tree

The test lists, the lanes and the CI are described in dev/plans/S2.md.


Repository layout

config.m4, config.w32, php_true_async.h   build and module entry
src/                                      extension sources
tests/                                    tests by group; tests/lists/ holds the frozen lists
tools/                                    runner, list checker, mutation and CI scripts
dev/                                      plan, principles, decisions, workflow

Support the project

If you find TrueAsync useful, you can support its development:

Donate via Giveth


License

BSD-3-Clause, see LICENSE.

About

Reference scheduler extension for the PHP Async Core ABI. The C implementation of the scheduler hooks

Topics

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages