From 68bdedaa31ee51b2582f123b936d9c11093e4789 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Wed, 19 Aug 2026 16:48:31 +0800 Subject: [PATCH] perf(gc): increase native heap initial threshold to 16 MiB - Updated default initial collection threshold from 10 MiB to 16 MiB - Increased test loop iterations to accommodate new memory threshold - Removed padding fields from native class test objects - Adjusted gc-threshold test to allocate 1100000 objects instead of 300000 - Updated documentation to reflect new 16 MiB initial threshold value - Modified multiple native class test files to align with new threshold settings --- docs/NATIVE_CLASS_IMPLEMENTATION_AUDIT.md | 2 +- docs/NATIVE_CLASS_OBJECT.md | 11 ++++++----- .../compiler/native-class/failed-clone-finalizer.phpt | 3 +-- .../native-class/failed-lifecycle-escape.phpt | 3 +-- tests/compiler/native-class/finalizer-allocation.phpt | 3 +-- .../native-class/finalizer-inheritance-exception.phpt | 3 +-- tests/compiler/native-class/gc-threshold.phpt | 9 ++------- tests/compiler/native-class/lifecycle-exceptions.phpt | 3 +-- 8 files changed, 14 insertions(+), 23 deletions(-) diff --git a/docs/NATIVE_CLASS_IMPLEMENTATION_AUDIT.md b/docs/NATIVE_CLASS_IMPLEMENTATION_AUDIT.md index 8f5507d4..0eb876e9 100644 --- a/docs/NATIVE_CLASS_IMPLEMENTATION_AUDIT.md +++ b/docs/NATIVE_CLASS_IMPLEMENTATION_AUDIT.md @@ -90,7 +90,7 @@ |---|---|---|---| | Wren 风格精确、非移动、STW mark-sweep | `phpx/thirdparty/wren-gc`、`native_gc.cc` | PHPX `wren_gc.*` | 已验证 | | 裸指针写入无 RC、无 write barrier | Native pointer field/local codegen | 生成 C++ 审查、Native PHPT | 已验证 | -| 10 MiB 初始阈值、1 MiB 下限、50% headroom | Wren GC 配置 | `wren_gc.uses_stable_native_heap_defaults` | 已验证 | +| 16 MiB 初始阈值、1 MiB 下限、50% headroom | Wren GC 配置 | `wren_gc.uses_stable_native_heap_defaults` | 已验证 | | 精确 root frame 保持对象图存活 | `NativeRootFrame`、generated root slots | PHPX root tests、`gc-cycle.phpt` | 已验证 | | Fiber 非 LIFO 生命周期安全 | root frame registry | `fiber-lifetime.phpt`、`fiber-shutdown.phpt`、PHPX Fiber root tests | 已验证 | | global/static request roots 在 ZTS 下为 thread-local | generated globals/root registration | ZTS 环境下 `global-and-static.phpt`、PHPX request root tests | 已验证 | diff --git a/docs/NATIVE_CLASS_OBJECT.md b/docs/NATIVE_CLASS_OBJECT.md index 63ad573c..ea8b1dfa 100644 --- a/docs/NATIVE_CLASS_OBJECT.md +++ b/docs/NATIVE_CLASS_OBJECT.md @@ -733,18 +733,19 @@ PHPX 的 Native GC adapter 负责类型 descriptor、root frame、C++ 析构回 首版采用以下固定默认值: -- 首次收集阈值:10 MiB。 +- 首次收集阈值:16 MiB。 - 收集后的最低阈值:1 MiB。 - 存活堆增长比例:50%。 - 下一次收集阈值:`max(1 MiB, liveBytes + liveBytes * 50%)`。 -这组参数沿用 Wren 的成熟默认值。阈值会随每轮收集后的实际存活字节数自动伸缩, +自适应增长策略沿用 Wren 的成熟设计;TypePHP 将首次阈值设为更规整的 16 MiB。 +阈值会随每轮收集后的实际存活字节数自动伸缩, 但不读取 PHP `memory_limit`、主机物理内存或容器内存。PHP `memory_limit` 面向 Zend 请求内存,常见的 128 MiB 默认值不能代表常驻 TypePHP 程序的 Native Heap 预算;按主机内存同比放大阈值也会使相同程序在不同机器上表现不稳定。 -10 MiB 只表示首次触发完整收集前允许的累计 Native allocation,并不是预留或立即 -申请 10 MiB。1 MiB 下限避免小型存活集反复触发 stop-the-world 收集;50% headroom +16 MiB 只表示首次触发完整收集前允许的累计 Native allocation,并不是预留或立即 +申请 16 MiB。1 MiB 下限避免小型存活集反复触发 stop-the-world 收集;50% headroom 在扫描 CPU 与额外内存之间采取比 Go 默认 100% 更保守的折中,因为首版 collector 是单线程 stop-the-world,而不是并发 collector。后续只能依据 TypePHP 的真实分配率、 存活率、暂停时间和峰值内存 benchmark 调整这些内部常量,不开放语言级 GC 调参接口。 @@ -1428,7 +1429,7 @@ Native Class 的主要路径必须满足: - Native Object 永远不能转换或赋值为 Interface 类型;`implements` 只提供编译期契约 校验,首版不提供调用点特化、fat pointer 或 interface table。 -- Native Heap 使用 10 MiB 首次阈值、1 MiB 最低阈值和 50% live-heap headroom。 +- Native Heap 使用 16 MiB 首次阈值、1 MiB 最低阈值和 50% live-heap headroom。 这些约定已经固定。后续 benchmark 可以调整 GC 的内部数值,但不得改变 Native Object 不做 Interface 类型擦除、没有 Zend 表示、热路径使用裸指针 Native Call 的基本设计。 diff --git a/tests/compiler/native-class/failed-clone-finalizer.phpt b/tests/compiler/native-class/failed-clone-finalizer.phpt index 7a776c8f..01627f2e 100644 --- a/tests/compiler/native-class/failed-clone-finalizer.phpt +++ b/tests/compiler/native-class/failed-clone-finalizer.phpt @@ -25,12 +25,11 @@ class NativeFailedCloneFinalizer class NativeFailedClonePressure { public int $value; - public int $padding; } function forceFailedCloneCollection(): void { - for ($i = 0; $i < 400000; $i++) { + for ($i = 0; $i < 800000; $i++) { new NativeFailedClonePressure(); } } diff --git a/tests/compiler/native-class/failed-lifecycle-escape.phpt b/tests/compiler/native-class/failed-lifecycle-escape.phpt index c8c4ffdf..7f72cdf6 100644 --- a/tests/compiler/native-class/failed-lifecycle-escape.phpt +++ b/tests/compiler/native-class/failed-lifecycle-escape.phpt @@ -68,12 +68,11 @@ class NativeFailedCloneEscape class NativeFailedLifecyclePressure { public int $value; - public int $padding; } function forceNativeCollection(): void { - for ($i = 0; $i < 400000; $i++) { + for ($i = 0; $i < 800000; $i++) { $filler = new NativeFailedLifecyclePressure(); } } diff --git a/tests/compiler/native-class/finalizer-allocation.phpt b/tests/compiler/native-class/finalizer-allocation.phpt index 5737c553..5b8cbe75 100644 --- a/tests/compiler/native-class/finalizer-allocation.phpt +++ b/tests/compiler/native-class/finalizer-allocation.phpt @@ -28,7 +28,6 @@ class NativeFinalizerCreator class NativeFinalizerFiller { public int $value; - public int $padding; } function main(): void @@ -39,7 +38,7 @@ function main(): void $creator = new NativeFinalizerCreator(); $creator = null; - for ($i = 0; $i < 400000; $i++) { + for ($i = 0; $i < 800000; $i++) { $filler = new NativeFinalizerFiller(); } diff --git a/tests/compiler/native-class/finalizer-inheritance-exception.phpt b/tests/compiler/native-class/finalizer-inheritance-exception.phpt index 81a04edb..384c0dfc 100644 --- a/tests/compiler/native-class/finalizer-inheritance-exception.phpt +++ b/tests/compiler/native-class/finalizer-inheritance-exception.phpt @@ -28,12 +28,11 @@ class NativeThrowingFinalizerChild extends NativeThrowingFinalizerBase class NativeFinalizerPressureObject { public int $value; - public int $padding; } function collectThrowingFinalizer(): void { - for ($i = 0; $i < 400000; $i++) { + for ($i = 0; $i < 800000; $i++) { try { $filler = new NativeFinalizerPressureObject(); } catch (RuntimeException $error) { diff --git a/tests/compiler/native-class/gc-threshold.phpt b/tests/compiler/native-class/gc-threshold.phpt index 3327cc5a..d66d8c5e 100644 --- a/tests/compiler/native-class/gc-threshold.phpt +++ b/tests/compiler/native-class/gc-threshold.phpt @@ -6,12 +6,6 @@ Native class: long-running allocation triggers automatic tracing collection #[Native] class NativeGcThresholdValue { - // Keep the pressure in the object payload so this test does not depend on - // the implementation size of the hidden Native GC header. - public int $padding1; - public int $padding2; - public int $padding3; - public function __destruct() { global $nativeGcFinalized; @@ -23,7 +17,8 @@ function main(): void { global $nativeGcFinalized; $nativeGcFinalized = 0; - for ($i = 0; $i < 300000; $i++) { + // Allocate enough compact objects to cross the default 16 MiB threshold. + for ($i = 0; $i < 1100000; $i++) { $value = new NativeGcThresholdValue(); } var_dump($nativeGcFinalized > 0); diff --git a/tests/compiler/native-class/lifecycle-exceptions.phpt b/tests/compiler/native-class/lifecycle-exceptions.phpt index 910a8e18..7c7439db 100644 --- a/tests/compiler/native-class/lifecycle-exceptions.phpt +++ b/tests/compiler/native-class/lifecycle-exceptions.phpt @@ -66,13 +66,12 @@ class NativeThrowingFinalizer class NativeLifecycleFiller { public int $value; - public int $padding; } function allocateUntilFinalizerRuns(): void { global $nativeFinalizers; - for ($i = 0; $i < 400000; $i++) { + for ($i = 0; $i < 800000; $i++) { try { $filler = new NativeLifecycleFiller(); } catch (RuntimeException $error) {