Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
e057b3a
#53: Refactor HTTP server to event-driven architecture with stream_s…
EdmondDantes Sep 6, 2025
88eb2e4
#53: * fixes to STREAM test behavior
EdmondDantes Sep 8, 2025
02d83c9
#53: + Add new tests for stream_select()
EdmondDantes Sep 8, 2025
35e4956
#53: + 024-stream_select_remote_disconnect.phpt
EdmondDantes Sep 9, 2025
d15692f
#53: + tcp_client_disconnect.php
EdmondDantes Sep 9, 2025
92a5c75
#53: Refactor async networking to use unified event handling
EdmondDantes Sep 10, 2025
a8175fd
#53: Fix SSL client-server test certificate and handshake issues
EdmondDantes Sep 10, 2025
94a0e32
#53: * some fixes for test 026
EdmondDantes Sep 11, 2025
1f1c5d1
#53: Refactor SSL tests to use shared certificate files
EdmondDantes Sep 11, 2025
742955d
#53: * fix test 016-tcp_stream_socket_accept_timeout.phpt
EdmondDantes Sep 11, 2025
f64196f
#53: * fix SSL tests 025, 026 and 027
EdmondDantes Sep 11, 2025
ad1468e
#53: % Fix infinite loop in HTTP server by removing stream_select
EdmondDantes Sep 12, 2025
91bc0bd
#53: % change status: OK
EdmondDantes Sep 12, 2025
2d97043
#53: % change status: OK
EdmondDantes Sep 12, 2025
90597ba
#53: % Optimize network_async_accept_incoming: try accept() first bef…
EdmondDantes Sep 12, 2025
695366b
#53: Fix socket closure order in both regular and SSL socket implemen…
EdmondDantes Sep 12, 2025
eb54e6d
#53: Add zend_async_poll_proxy_t for FD resource optimization
EdmondDantes Sep 13, 2025
d0a31b9
#53: Fix poll proxy event aggregation and lifecycle management
EdmondDantes Sep 13, 2025
1e1c331
#53: * Handling the special case with the UV_EBADF code
EdmondDantes Sep 13, 2025
e698c3b
#53: Optimize poll proxy event handling and callback parameters
EdmondDantes Sep 13, 2025
79849e6
#53: Add zend_async_poll_proxy_t for FD resource optimization
EdmondDantes Sep 14, 2025
d545ff8
Merge branch '53-optimize-descriptor-registration-in-event-loop' into…
EdmondDantes Sep 14, 2025
f950281
#53: Optimize libuv reactor with automatic waker event cleanup
EdmondDantes Sep 14, 2025
67ed06c
#53: * fix stop_waker_events_for_new_coroutines
EdmondDantes Sep 14, 2025
08002d0
#53: * fix stop_waker_events_for_new_coroutines
EdmondDantes Sep 14, 2025
0a5a50d
#53: * remove LIBUV_CLEAR_WAKER_EVENTS_AFTER_EXECUTE
EdmondDantes Sep 14, 2025
6ff73b5
#53: * Optimize scheduler_next_tick to reduce LIBUV calls
EdmondDantes Sep 14, 2025
1037b9f
#53: * Optimize scheduler_next_tick to reduce LIBUV calls2
EdmondDantes Sep 15, 2025
e497ebe
#53: Implement waker events cleanup for resumed coroutines
EdmondDantes Sep 15, 2025
0c4c4e6
#53: Fix waker events cleanup for buffer reallocation cases
EdmondDantes Sep 15, 2025
f3c4348
#53: Fix 010-stream_select_async and issue with poll event => proxy_…
EdmondDantes Sep 15, 2025
b8832ec
#53: Add to scheduler.c logic Waker clean after EventLoop tick
EdmondDantes Sep 15, 2025
793e9a0
#53: + Add UDP tests for Socket Stream
EdmondDantes Sep 17, 2025
0365a46
#53: fix 028-udp_basic_operations.phpt
EdmondDantes Sep 18, 2025
ca77379
#53: fix 029-udp_concurrent_operations.phpt
EdmondDantes Sep 18, 2025
840d4f1
#53: fix 029-udp_concurrent_operations.phpt
EdmondDantes Sep 18, 2025
508f111
#53: fix sock_async_poll
EdmondDantes Sep 19, 2025
e34d7d1
#53: Optimize async socket timeout tests for faster execution
EdmondDantes Sep 19, 2025
c397718
#53: Looking at the completed optimization work, here's a commit des…
EdmondDantes Sep 20, 2025
fc5db30
#53: * fix deadlock tests and fix zend_async_event_callback_new
EdmondDantes Sep 20, 2025
b4e3886
#53: Add separate queue for resumed coroutines to improve event clea…
EdmondDantes Sep 20, 2025
c365221
#53: * fix await iterator logic
EdmondDantes Sep 20, 2025
47b218c
#53: + Update CHANGELOG.md
EdmondDantes Sep 21, 2025
362e937
#53: * fix memory leak by resumed_coroutines logic
EdmondDantes Sep 21, 2025
e499a4d
Merge remote-tracking branch 'origin/53-optimize-descriptor-registrat…
EdmondDantes Sep 21, 2025
d4da78c
#53: * fix memory leak by resumed_coroutines logic
EdmondDantes Sep 21, 2025
20027c7
#53: + add logger for http server
EdmondDantes Sep 21, 2025
36114a1
#53: + Apply code format
EdmondDantes Sep 21, 2025
0e2f9d9
#53: Fix deprecated OPcache configuration in CI workflows
EdmondDantes Sep 21, 2025
88230f3
#53: * change 005-socket_accept_multiple.phpt
EdmondDantes Sep 21, 2025
09bc2b8
#53: * change 005-socket_accept_multiple.phpt
EdmondDantes Sep 21, 2025
f3e3646
#53: * Upgrade LibUV to version 1.45 due to a timer bug that causes …
EdmondDantes Sep 22, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/build-alpine.yml
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,6 @@ jobs:
run: |
/usr/local/bin/php ../../run-tests.php \
${{ matrix.asan && '--asan' || '' }} \
-d zend_extension=opcache.so \
-d opcache.enable_cli=1 \
-d opcache.jit_buffer_size=64M \
-d opcache.jit=tracing \
Expand All @@ -241,7 +240,6 @@ jobs:
run: |
/usr/local/bin/php ../../run-tests.php \
${{ matrix.asan && '--asan' || '' }} \
-d zend_extension=opcache.so \
-d opcache.enable_cli=1 \
-P -q -x -j$(nproc) \
-g FAIL,BORK,LEAK,XLEAK \
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/build-freebsd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ jobs:
--show-diff \
--show-slow 4000 \
--set-timeout 120 \
-d zend_extension=opcache.so \
-d opcache.enable_cli=1 \
ext/async/tests

Expand All @@ -180,7 +179,6 @@ jobs:
--show-diff \
--show-slow 4000 \
--set-timeout 120 \
-d zend_extension=opcache.so \
-d opcache.enable_cli=1 \
-d opcache.jit_buffer_size=64M \
-d opcache.jit=tracing \
Expand All @@ -195,7 +193,6 @@ jobs:
--show-diff \
--show-slow 4000 \
--set-timeout 120 \
-d zend_extension=opcache.so \
-d opcache.enable_cli=1 \
-d opcache.jit_buffer_size=64M \
-d opcache.jit=function \
Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/build-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ jobs:
libxslt1-dev \
libicu-dev

# Build LibUV from source (need >= 1.44.0)
# Build LibUV from source (need >= 1.45.0)
sudo apt-get install -y cmake ninja-build

# Download and build LibUV 1.48.0
Expand Down Expand Up @@ -270,7 +270,6 @@ jobs:

/usr/local/bin/php ../../run-tests.php \
$TEST_PARAMS \
-d zend_extension=opcache.so \
-d opcache.enable_cli=1 \
-P -q -j$PARALLEL_JOBS \
-g FAIL,BORK,LEAK,XLEAK \
Expand All @@ -287,7 +286,6 @@ jobs:
working-directory: php-src/ext/async
run: |
/usr/local/bin/php ../../run-tests.php \
-d zend_extension=opcache.so \
-d opcache.enable_cli=1 \
-d opcache.jit_buffer_size=64M \
-d opcache.jit=tracing \
Expand All @@ -306,7 +304,6 @@ jobs:
working-directory: php-src/ext/async
run: |
/usr/local/bin/php ../../run-tests.php \
-d zend_extension=opcache.so \
-d opcache.enable_cli=1 \
-d opcache.jit_buffer_size=64M \
-d opcache.jit=function \
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/build-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,6 @@ jobs:
working-directory: php-src/ext/async
run: |
/usr/local/bin/php ../../run-tests.php \
-d zend_extension=opcache.so \
-d opcache.enable_cli=1 \
-d opcache.jit_buffer_size=64M \
-d opcache.jit=tracing \
Expand All @@ -175,7 +174,6 @@ jobs:
working-directory: php-src/ext/async
run: |
/usr/local/bin/php ../../run-tests.php \
-d zend_extension=opcache.so \
-d opcache.enable_cli=1 \
-P -q -x -j$(sysctl -n hw.logicalcpu) \
-g FAIL,BORK,LEAK,XLEAK \
Expand All @@ -191,7 +189,6 @@ jobs:
working-directory: php-src/ext/async
run: |
/usr/local/bin/php ../../run-tests.php \
-d zend_extension=opcache.so \
-d opcache.enable_cli=1 \
-d opcache.jit_buffer_size=64M \
-d opcache.jit=function \
Expand Down
26 changes: 12 additions & 14 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,40 +70,40 @@ jobs:
firebird-dev \
valgrind cmake

# Cache LibUV 1.44.0 installation to avoid rebuilding
- name: Cache LibUV 1.44.0
# Cache LibUV 1.45.0 installation to avoid rebuilding
- name: Cache LibUV 1.45.0
id: cache-libuv
uses: actions/cache@v4
with:
path: |
/usr/local/lib/libuv*
/usr/local/include/uv*
/usr/local/lib/pkgconfig/libuv.pc
key: ${{ runner.os }}-libuv-1.44.0-release
key: ${{ runner.os }}-libuv-1.45.0-release

- name: Install LibUV >= 1.44.0
- name: Install LibUV >= 1.45.0
run: |
# Check if we have cached LibUV 1.44.0
# Check if we have cached LibUV 1.45.0
if [ "${{ steps.cache-libuv.outputs.cache-hit }}" == "true" ]; then
echo "Using cached LibUV 1.44.0 installation"
echo "Using cached LibUV 1.45.0 installation"
sudo ldconfig
echo "LibUV version: $(pkg-config --modversion libuv)"
# Check if system libuv meets requirements
elif pkg-config --exists libuv && pkg-config --atleast-version=1.44.0 libuv; then
elif pkg-config --exists libuv && pkg-config --atleast-version=1.45.0 libuv; then
echo "System libuv version: $(pkg-config --modversion libuv)"
sudo apt-get install -y libuv1-dev
else
echo "Installing LibUV 1.44.0 from source"
wget https://github.com/libuv/libuv/archive/v1.44.0.tar.gz
tar -xzf v1.44.0.tar.gz
cd libuv-1.44.0
echo "Installing LibUV 1.45.0 from source"
wget https://github.com/libuv/libuv/archive/v1.45.0.tar.gz
tar -xzf v1.45.0.tar.gz
cd libuv-1.45.0
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
sudo make install
sudo ldconfig
cd ../..
echo "LibUV 1.44.0 compiled and installed"
echo "LibUV 1.45.0 compiled and installed"
fi

- name: Configure PHP
Expand All @@ -113,7 +113,6 @@ jobs:
./configure \
--enable-zts \
--enable-fpm \
--enable-opcache \
--with-pdo-mysql=mysqlnd \
--with-mysqli=mysqlnd \
--with-pgsql \
Expand Down Expand Up @@ -178,7 +177,6 @@ jobs:
run: |
/usr/local/bin/php -v
/usr/local/bin/php ../../run-tests.php \
-d zend_extension=opcache.so \
-d opcache.enable_cli=1 \
-d opcache.jit_buffer_size=64M \
-d opcache.jit=tracing \
Expand Down
31 changes: 30 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,36 @@ All notable changes to the Async extension for PHP will be documented in this fi
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
## [0.4.0] - 2025-09-31

### Added
- **UDP socket stream support for TrueAsync**
- **SSL support for socket stream**
- **Poll Proxy**: New `zend_async_poll_proxy_t` structure for optimized file descriptor management
- Efficient caching of event handlers to reduce EventLoop creation overhead
- Poll proxy event aggregation and improved lifecycle management

### Fixed
- **Fixing `ref_count` logic for the `zend_async_event_callback_t` structure**:
- The add/dispose methods correctly increment the counter
- Memory leaks fixed
- Fixed await iterator logic for `awaitXXX` functions

### Changed
- **Memory Optimization**: Enhanced memory allocation for async structures
- Optimized waker trigger structures with improved memory layout
- Enhanced memory management for poll proxy events
- Better resource cleanup and lifecycle management
- **Event Loop Performance**: Major scheduler optimizations
- **Automatic Event Cleanup**: Added automatic waker event cleanup when coroutines resume (see `ZEND_ASYNC_WAKER_CLEAN_EVENTS`)
- Separate queue implementation for resumed coroutines to improve stability
- Reduced unnecessary LibUV calls in scheduler tick processing
- **Socket Performance**:
- Event handler caching for sockets to avoid constant EventLoop recreation
- Optimized `network_async_accept_incoming` to try `accept()` before waiting
- Enhanced stream_select functionality with event-driven architecture
- Improved blocking operation handling with boolean return values
- Upgrade `LibUV` to version `1.45` due to a timer bug that causes the application to hang

## [0.3.0] - 2025-07-16

Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ docker run --rm true-async-php php -m | grep true_async
### Requirements

- **PHP 8.5.0+**
- **LibUV ≥ 1.44.0** (required) - Fixes critical `UV_RUN_ONCE` busy loop issue that could cause high CPU usage
- **LibUV ≥ 1.45.0** (required) - Fixes critical `UV_RUN_ONCE` busy loop issue that could cause high CPU usage

### Why LibUV 1.44.0+ is Required
### Why LibUV 1.45.0+ is Required

Prior to libuv 1.44, there was a critical issue in `uv__io_poll()`/`uv__run_pending` logic that could cause the event loop to "stick" after the first callback when running in `UV_RUN_ONCE` mode, especially when new ready events appeared within callbacks. This resulted in:

Expand Down Expand Up @@ -95,17 +95,17 @@ The fix in libuv 1.44 ensures that `UV_RUN_ONCE` properly returns after processi

4. **Install LibUV:**:

**IMPORTANT:** LibUV version 1.44.0 or later is required.
**IMPORTANT:** LibUV version 1.45.0 or later is required.

For Debian/Ubuntu:
```bash
# Check if system libuv meets requirements (≥1.44.0)
# Check if system libuv meets requirements (≥1.45.0)
pkg-config --modversion libuv

# If version is too old, install from source:
wget https://github.com/libuv/libuv/archive/v1.44.0.tar.gz
tar -xzf v1.44.0.tar.gz
cd libuv-1.44.0
wget https://github.com/libuv/libuv/archive/v1.45.0.tar.gz
tar -xzf v1.45.0.tar.gz
cd libuv-1.45.0
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
Expand Down
7 changes: 6 additions & 1 deletion async.c
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,9 @@ static PHP_GINIT_FUNCTION(async)
/* Maximum number of coroutines in the concurrent iterator */
async_globals->default_concurrency = 32;

/* Initialize reactor execution optimization */
async_globals->last_reactor_tick = 0;

#ifdef PHP_WIN32
async_globals->watcherThread = NULL;
async_globals->ioCompletionPort = NULL;
Expand All @@ -907,7 +910,8 @@ static PHP_GINIT_FUNCTION(async)
}

/* {{{ PHP_GSHUTDOWN_FUNCTION */
static PHP_GSHUTDOWN_FUNCTION(async){
static PHP_GSHUTDOWN_FUNCTION(async)
{
#ifdef PHP_WIN32
#endif
} /* }}} */
Expand Down Expand Up @@ -959,6 +963,7 @@ PHP_RINIT_FUNCTION(async) /* {{{ */
ZEND_ASYNC_INITIALIZE;
circular_buffer_ctor(&ASYNC_G(microtasks), 64, sizeof(zend_async_microtask_t *), &zend_std_allocator);
circular_buffer_ctor(&ASYNC_G(coroutine_queue), 128, sizeof(zend_coroutine_t *), &zend_std_allocator);
circular_buffer_ctor(&ASYNC_G(resumed_coroutines), 64, sizeof(zend_coroutine_t *), &zend_std_allocator);
zend_hash_init(&ASYNC_G(coroutines), 128, NULL, NULL, 0);

ASYNC_G(reactor_started) = false;
Expand Down
4 changes: 3 additions & 1 deletion async_API.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ static void engine_shutdown(void)

circular_buffer_dtor(&ASYNC_G(microtasks));
circular_buffer_dtor(&ASYNC_G(coroutine_queue));
circular_buffer_dtor(&ASYNC_G(resumed_coroutines));
zend_hash_destroy(&ASYNC_G(coroutines));

if (ASYNC_G(root_context) != NULL) {
Expand Down Expand Up @@ -609,7 +610,8 @@ static void await_iterator_dispose(async_await_iterator_t *iterator, async_itera
iterator->zend_iterator = NULL;

// When the iterator has finished, it’s now possible to specify the exact number of elements since it’s known.
iterator->await_context->total = iterator->await_context->futures_count;
iterator->await_context->total =
iterator->await_context->futures_count + iterator->await_context->resolved_count;

// Scenario: the iterator has already finished, and there’s nothing left to await.
// In that case, the coroutine needs to be terminated.
Expand Down
Loading
Loading