Skip to content

Commit 4bc433b

Browse files
authored
Merge pull request #60 from true-async/53-optimize-descriptor-registration-in-event-loop
53 optimize descriptor registration in event loop
2 parents 2fc2adf + f3e3646 commit 4bc433b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2121
-299
lines changed

.github/workflows/build-alpine.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,6 @@ jobs:
224224
run: |
225225
/usr/local/bin/php ../../run-tests.php \
226226
${{ matrix.asan && '--asan' || '' }} \
227-
-d zend_extension=opcache.so \
228227
-d opcache.enable_cli=1 \
229228
-d opcache.jit_buffer_size=64M \
230229
-d opcache.jit=tracing \
@@ -241,7 +240,6 @@ jobs:
241240
run: |
242241
/usr/local/bin/php ../../run-tests.php \
243242
${{ matrix.asan && '--asan' || '' }} \
244-
-d zend_extension=opcache.so \
245243
-d opcache.enable_cli=1 \
246244
-P -q -x -j$(nproc) \
247245
-g FAIL,BORK,LEAK,XLEAK \

.github/workflows/build-freebsd.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ jobs:
167167
--show-diff \
168168
--show-slow 4000 \
169169
--set-timeout 120 \
170-
-d zend_extension=opcache.so \
171170
-d opcache.enable_cli=1 \
172171
ext/async/tests
173172
@@ -180,7 +179,6 @@ jobs:
180179
--show-diff \
181180
--show-slow 4000 \
182181
--set-timeout 120 \
183-
-d zend_extension=opcache.so \
184182
-d opcache.enable_cli=1 \
185183
-d opcache.jit_buffer_size=64M \
186184
-d opcache.jit=tracing \
@@ -195,7 +193,6 @@ jobs:
195193
--show-diff \
196194
--show-slow 4000 \
197195
--set-timeout 120 \
198-
-d zend_extension=opcache.so \
199196
-d opcache.enable_cli=1 \
200197
-d opcache.jit_buffer_size=64M \
201198
-d opcache.jit=function \

.github/workflows/build-linux.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ jobs:
9898
libxslt1-dev \
9999
libicu-dev
100100
101-
# Build LibUV from source (need >= 1.44.0)
101+
# Build LibUV from source (need >= 1.45.0)
102102
sudo apt-get install -y cmake ninja-build
103103
104104
# Download and build LibUV 1.48.0
@@ -270,7 +270,6 @@ jobs:
270270
271271
/usr/local/bin/php ../../run-tests.php \
272272
$TEST_PARAMS \
273-
-d zend_extension=opcache.so \
274273
-d opcache.enable_cli=1 \
275274
-P -q -j$PARALLEL_JOBS \
276275
-g FAIL,BORK,LEAK,XLEAK \
@@ -287,7 +286,6 @@ jobs:
287286
working-directory: php-src/ext/async
288287
run: |
289288
/usr/local/bin/php ../../run-tests.php \
290-
-d zend_extension=opcache.so \
291289
-d opcache.enable_cli=1 \
292290
-d opcache.jit_buffer_size=64M \
293291
-d opcache.jit=tracing \
@@ -306,7 +304,6 @@ jobs:
306304
working-directory: php-src/ext/async
307305
run: |
308306
/usr/local/bin/php ../../run-tests.php \
309-
-d zend_extension=opcache.so \
310307
-d opcache.enable_cli=1 \
311308
-d opcache.jit_buffer_size=64M \
312309
-d opcache.jit=function \

.github/workflows/build-macos.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ jobs:
159159
working-directory: php-src/ext/async
160160
run: |
161161
/usr/local/bin/php ../../run-tests.php \
162-
-d zend_extension=opcache.so \
163162
-d opcache.enable_cli=1 \
164163
-d opcache.jit_buffer_size=64M \
165164
-d opcache.jit=tracing \
@@ -175,7 +174,6 @@ jobs:
175174
working-directory: php-src/ext/async
176175
run: |
177176
/usr/local/bin/php ../../run-tests.php \
178-
-d zend_extension=opcache.so \
179177
-d opcache.enable_cli=1 \
180178
-P -q -x -j$(sysctl -n hw.logicalcpu) \
181179
-g FAIL,BORK,LEAK,XLEAK \
@@ -191,7 +189,6 @@ jobs:
191189
working-directory: php-src/ext/async
192190
run: |
193191
/usr/local/bin/php ../../run-tests.php \
194-
-d zend_extension=opcache.so \
195192
-d opcache.enable_cli=1 \
196193
-d opcache.jit_buffer_size=64M \
197194
-d opcache.jit=function \

.github/workflows/build.yml

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,40 +70,40 @@ jobs:
7070
firebird-dev \
7171
valgrind cmake
7272
73-
# Cache LibUV 1.44.0 installation to avoid rebuilding
74-
- name: Cache LibUV 1.44.0
73+
# Cache LibUV 1.45.0 installation to avoid rebuilding
74+
- name: Cache LibUV 1.45.0
7575
id: cache-libuv
7676
uses: actions/cache@v4
7777
with:
7878
path: |
7979
/usr/local/lib/libuv*
8080
/usr/local/include/uv*
8181
/usr/local/lib/pkgconfig/libuv.pc
82-
key: ${{ runner.os }}-libuv-1.44.0-release
82+
key: ${{ runner.os }}-libuv-1.45.0-release
8383

84-
- name: Install LibUV >= 1.44.0
84+
- name: Install LibUV >= 1.45.0
8585
run: |
86-
# Check if we have cached LibUV 1.44.0
86+
# Check if we have cached LibUV 1.45.0
8787
if [ "${{ steps.cache-libuv.outputs.cache-hit }}" == "true" ]; then
88-
echo "Using cached LibUV 1.44.0 installation"
88+
echo "Using cached LibUV 1.45.0 installation"
8989
sudo ldconfig
9090
echo "LibUV version: $(pkg-config --modversion libuv)"
9191
# Check if system libuv meets requirements
92-
elif pkg-config --exists libuv && pkg-config --atleast-version=1.44.0 libuv; then
92+
elif pkg-config --exists libuv && pkg-config --atleast-version=1.45.0 libuv; then
9393
echo "System libuv version: $(pkg-config --modversion libuv)"
9494
sudo apt-get install -y libuv1-dev
9595
else
96-
echo "Installing LibUV 1.44.0 from source"
97-
wget https://github.com/libuv/libuv/archive/v1.44.0.tar.gz
98-
tar -xzf v1.44.0.tar.gz
99-
cd libuv-1.44.0
96+
echo "Installing LibUV 1.45.0 from source"
97+
wget https://github.com/libuv/libuv/archive/v1.45.0.tar.gz
98+
tar -xzf v1.45.0.tar.gz
99+
cd libuv-1.45.0
100100
mkdir build && cd build
101101
cmake .. -DCMAKE_BUILD_TYPE=Release
102102
make -j$(nproc)
103103
sudo make install
104104
sudo ldconfig
105105
cd ../..
106-
echo "LibUV 1.44.0 compiled and installed"
106+
echo "LibUV 1.45.0 compiled and installed"
107107
fi
108108
109109
- name: Configure PHP
@@ -113,7 +113,6 @@ jobs:
113113
./configure \
114114
--enable-zts \
115115
--enable-fpm \
116-
--enable-opcache \
117116
--with-pdo-mysql=mysqlnd \
118117
--with-mysqli=mysqlnd \
119118
--with-pgsql \
@@ -178,7 +177,6 @@ jobs:
178177
run: |
179178
/usr/local/bin/php -v
180179
/usr/local/bin/php ../../run-tests.php \
181-
-d zend_extension=opcache.so \
182180
-d opcache.enable_cli=1 \
183181
-d opcache.jit_buffer_size=64M \
184182
-d opcache.jit=tracing \

CHANGELOG.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,36 @@ All notable changes to the Async extension for PHP will be documented in this fi
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## [Unreleased]
8+
## [0.4.0] - 2025-09-31
9+
10+
### Added
11+
- **UDP socket stream support for TrueAsync**
12+
- **SSL support for socket stream**
13+
- **Poll Proxy**: New `zend_async_poll_proxy_t` structure for optimized file descriptor management
14+
- Efficient caching of event handlers to reduce EventLoop creation overhead
15+
- Poll proxy event aggregation and improved lifecycle management
16+
17+
### Fixed
18+
- **Fixing `ref_count` logic for the `zend_async_event_callback_t` structure**:
19+
- The add/dispose methods correctly increment the counter
20+
- Memory leaks fixed
21+
- Fixed await iterator logic for `awaitXXX` functions
22+
23+
### Changed
24+
- **Memory Optimization**: Enhanced memory allocation for async structures
25+
- Optimized waker trigger structures with improved memory layout
26+
- Enhanced memory management for poll proxy events
27+
- Better resource cleanup and lifecycle management
28+
- **Event Loop Performance**: Major scheduler optimizations
29+
- **Automatic Event Cleanup**: Added automatic waker event cleanup when coroutines resume (see `ZEND_ASYNC_WAKER_CLEAN_EVENTS`)
30+
- Separate queue implementation for resumed coroutines to improve stability
31+
- Reduced unnecessary LibUV calls in scheduler tick processing
32+
- **Socket Performance**:
33+
- Event handler caching for sockets to avoid constant EventLoop recreation
34+
- Optimized `network_async_accept_incoming` to try `accept()` before waiting
35+
- Enhanced stream_select functionality with event-driven architecture
36+
- Improved blocking operation handling with boolean return values
37+
- Upgrade `LibUV` to version `1.45` due to a timer bug that causes the application to hang
938

1039
## [0.3.0] - 2025-07-16
1140

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ docker run --rm true-async-php php -m | grep true_async
4747
### Requirements
4848

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

52-
### Why LibUV 1.44.0+ is Required
52+
### Why LibUV 1.45.0+ is Required
5353

5454
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:
5555

@@ -95,17 +95,17 @@ The fix in libuv 1.44 ensures that `UV_RUN_ONCE` properly returns after processi
9595
9696
4. **Install LibUV:**:
9797
98-
**IMPORTANT:** LibUV version 1.44.0 or later is required.
98+
**IMPORTANT:** LibUV version 1.45.0 or later is required.
9999
100100
For Debian/Ubuntu:
101101
```bash
102-
# Check if system libuv meets requirements (≥1.44.0)
102+
# Check if system libuv meets requirements (≥1.45.0)
103103
pkg-config --modversion libuv
104104
105105
# If version is too old, install from source:
106-
wget https://github.com/libuv/libuv/archive/v1.44.0.tar.gz
107-
tar -xzf v1.44.0.tar.gz
108-
cd libuv-1.44.0
106+
wget https://github.com/libuv/libuv/archive/v1.45.0.tar.gz
107+
tar -xzf v1.45.0.tar.gz
108+
cd libuv-1.45.0
109109
mkdir build && cd build
110110
cmake .. -DCMAKE_BUILD_TYPE=Release
111111
make -j$(nproc)

async.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,9 @@ static PHP_GINIT_FUNCTION(async)
896896
/* Maximum number of coroutines in the concurrent iterator */
897897
async_globals->default_concurrency = 32;
898898

899+
/* Initialize reactor execution optimization */
900+
async_globals->last_reactor_tick = 0;
901+
899902
#ifdef PHP_WIN32
900903
async_globals->watcherThread = NULL;
901904
async_globals->ioCompletionPort = NULL;
@@ -907,7 +910,8 @@ static PHP_GINIT_FUNCTION(async)
907910
}
908911

909912
/* {{{ PHP_GSHUTDOWN_FUNCTION */
910-
static PHP_GSHUTDOWN_FUNCTION(async){
913+
static PHP_GSHUTDOWN_FUNCTION(async)
914+
{
911915
#ifdef PHP_WIN32
912916
#endif
913917
} /* }}} */
@@ -959,6 +963,7 @@ PHP_RINIT_FUNCTION(async) /* {{{ */
959963
ZEND_ASYNC_INITIALIZE;
960964
circular_buffer_ctor(&ASYNC_G(microtasks), 64, sizeof(zend_async_microtask_t *), &zend_std_allocator);
961965
circular_buffer_ctor(&ASYNC_G(coroutine_queue), 128, sizeof(zend_coroutine_t *), &zend_std_allocator);
966+
circular_buffer_ctor(&ASYNC_G(resumed_coroutines), 64, sizeof(zend_coroutine_t *), &zend_std_allocator);
962967
zend_hash_init(&ASYNC_G(coroutines), 128, NULL, NULL, 0);
963968

964969
ASYNC_G(reactor_started) = false;

async_API.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ static void engine_shutdown(void)
208208

209209
circular_buffer_dtor(&ASYNC_G(microtasks));
210210
circular_buffer_dtor(&ASYNC_G(coroutine_queue));
211+
circular_buffer_dtor(&ASYNC_G(resumed_coroutines));
211212
zend_hash_destroy(&ASYNC_G(coroutines));
212213

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

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

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

0 commit comments

Comments
 (0)