Summary
Playground currently enables OPcache, but generated php.ini forces it into file-cache-only mode:
opcache.enable = 1
opcache.enable_cli = 1
opcache.file_cache = /internal/shared/opcache
opcache.file_cache_only = 1
In local A/B testing, opcache.file_cache_only = 1 leaves warm WordPress/PHP requests paying a large per-request latency cost. Enabling the normal in-memory OPcache path for PHP 8.1+ while preserving file-cache-only mode for PHP 7.4 and 8.0 reduced warm request latency by roughly 10x for REST routes on current/default runtimes.
Public context
The current repo default/recommended PHP version is 8.3 (RecommendedPHPVersion), while @php-wasm/universal supports 7.4, 8.0, 8.1, 8.2, 8.3, 8.4, and 8.5.
Proposed shape
Avoid a global flip. A global file_cache_only = 0 crashed PHP 7.4 and 8.0 in local testing. The safer shape is version-gated:
const useInMemoryOpcache =
runtime.phpVersion.major > 8 ||
(runtime.phpVersion.major === 8 && runtime.phpVersion.minor >= 1);
'opcache.file_cache_only = ' + (useInMemoryOpcache ? '0' : '1')
This keeps conservative file-cache-only behavior for PHP 7.4 and 8.0, while enabling in-memory OPcache for PHP 8.1+.
A/B results
Same machine, same existing WordPress site, same probe, current behavior vs gated candidate. Values are median warm samples after initial warmup.
| PHP |
Current mode |
Candidate mode |
/wp-json/ current |
/wp-json/ candidate |
Speedup |
/ current |
/ candidate |
Speedup |
| 7.4 |
file-only |
file-only |
307.1ms |
304.6ms |
1.0x |
367.2ms |
375.9ms |
1.0x |
| 8.0 |
file-only |
file-only |
299.7ms |
287.3ms |
1.0x |
350.6ms |
341.7ms |
1.0x |
| 8.1 |
file-only |
memory + file |
313.5ms |
26.1ms |
12.0x |
374.7ms |
75.1ms |
5.0x |
| 8.2 |
file-only |
memory + file |
334.1ms |
30.0ms |
11.1x |
396.6ms |
89.5ms |
4.4x |
| 8.3 |
file-only |
memory + file |
310.5ms |
28.1ms |
11.0x |
387.7ms |
83.2ms |
4.7x |
| 8.4 |
file-only |
memory + file |
314.4ms |
28.4ms |
11.1x |
376.8ms |
79.9ms |
4.7x |
| 8.5 |
file-only |
memory + file |
357.4ms |
23.5ms |
15.2x |
405.1ms |
64.2ms |
6.3x |
For PHP 8.1+, opcache_get_status(false) reported opcache_enabled: true, cached scripts, and a hit rate around 66-67% in the probe. For PHP 7.4 and 8.0 the gated candidate kept file_cache_only = 1, matching current behavior.
Failure cutoff evidence
A global opcache.file_cache_only = 0 was tested first. It crashed on PHP 7.4 and PHP 8.0 with:
Error: PHP.run() failed with exit code -2
=== Stdout ===
=== Stderr ===
The gated PHP 8.1+ candidate avoided this by keeping file-cache-only mode for PHP versions older than 8.1.
Freshness check
For PHP 8.1 through 8.5, a direct edited-script freshness probe passed:
first request: v1
second request: v1
after immediate file edit: v2
delayed request: v2
This suggests file_cache_only = 0 did not introduce obvious stale-code behavior in the tested PHP 8.1+ range.
Targeted validation run
The gated candidate passed these targeted checks locally:
npx nx test-group-5-asyncify php-wasm-node --testFiles=php-opcache.spec.ts
# 6 tests passed
npx nx test-group-5-jspi php-wasm-node --testFiles=php-opcache.spec.ts
# 6 tests passed
npx nx test-group-1-asyncify php-wasm-node --testFiles=php-request-handler.spec.ts
# 411 tests passed
npx nx typecheck php-wasm-node
# passed
npx nx lint php-wasm-node
# passed
Why this matters
This affects the current/default Playground PHP path (8.3) and newer supported versions. For modern WordPress usage, the current file-cache-only mode appears to impose a large warm request tax on every PHP/REST request after the site is already running.
The version-gated change keeps older supported runtimes conservative while removing the unnecessary tax from PHP 8.1+.
Remaining validation before merging
- Browser Playground validation, not only Node/CLI.
- Longer memory soak for PHP 8.1+.
- More edit freshness scenarios, especially mounted plugin/theme files.
- Runtime rotation coverage.
- A wp-admin/editor navigation workload with the gated candidate.
Summary
Playground currently enables OPcache, but generated
php.iniforces it into file-cache-only mode:In local A/B testing,
opcache.file_cache_only = 1leaves warm WordPress/PHP requests paying a large per-request latency cost. Enabling the normal in-memory OPcache path for PHP 8.1+ while preserving file-cache-only mode for PHP 7.4 and 8.0 reduced warm request latency by roughly 10x for REST routes on current/default runtimes.Public context
The current repo default/recommended PHP version is
8.3(RecommendedPHPVersion), while@php-wasm/universalsupports7.4,8.0,8.1,8.2,8.3,8.4, and8.5.Proposed shape
Avoid a global flip. A global
file_cache_only = 0crashed PHP 7.4 and 8.0 in local testing. The safer shape is version-gated:This keeps conservative file-cache-only behavior for PHP 7.4 and 8.0, while enabling in-memory OPcache for PHP 8.1+.
A/B results
Same machine, same existing WordPress site, same probe, current behavior vs gated candidate. Values are median warm samples after initial warmup.
/wp-json/current/wp-json/candidate/current/candidateFor PHP 8.1+,
opcache_get_status(false)reportedopcache_enabled: true, cached scripts, and a hit rate around 66-67% in the probe. For PHP 7.4 and 8.0 the gated candidate keptfile_cache_only = 1, matching current behavior.Failure cutoff evidence
A global
opcache.file_cache_only = 0was tested first. It crashed on PHP 7.4 and PHP 8.0 with:The gated PHP 8.1+ candidate avoided this by keeping file-cache-only mode for PHP versions older than 8.1.
Freshness check
For PHP 8.1 through 8.5, a direct edited-script freshness probe passed:
This suggests
file_cache_only = 0did not introduce obvious stale-code behavior in the tested PHP 8.1+ range.Targeted validation run
The gated candidate passed these targeted checks locally:
Why this matters
This affects the current/default Playground PHP path (
8.3) and newer supported versions. For modern WordPress usage, the current file-cache-only mode appears to impose a large warm request tax on every PHP/REST request after the site is already running.The version-gated change keeps older supported runtimes conservative while removing the unnecessary tax from PHP 8.1+.
Remaining validation before merging