Hi internals,
Before I sit down and write a full RFC, I'd like to get a feel for where people stand on something I've been working toward for a while: deprecating not passing --enable-zts, and removing the NTS mode entirely in the next major version.
First a very important clarification: I'm not looking to deprecate the way FPM or other process managers work. All the existing NTS functionality, including hard timeouts (which do not yet have ZTS equivalent) can keep working in a single threaded ZTS run.
The reasons, listed by importance:
- the current split introduces a lot of unnecessary builds and poor availability (especially for FrankenPHP and other emerging projects that require thread safety):
- OS distributions generally only package NTS
- Remi used to ship cli-only ZTS php, but stopped because it meant twice the maintenance.
- Ondrej doesn't want to take on ZTS builds because NTS is the default, again citing twice the work
- Shivam's Homebrew does ship both NTS and ZTS, but only extensions for NTS. PIE exists, but extension providers suffer from the same problems: most either don't do prebuilt binaries at all or only do NTS.
- I ship ZTS packages only because there's no other availability for them. In order not to conflict with users' regular system packages and their dependencies, I build everything into a different name.
- php-src's GitHub CI would shrink significantly by getting rid of NTS
- Most users don't even know that a ZTS build with ext-parallel capabilities exists, if they do, it mostly just confuses them on which to get
- Tl;dr: nobody wants to maintain two builds and even having a necessary split is making things hard.
- maintenance cost in php-src itself: ~420 #ifdef ZTS results and ~30 for #ifndef ZTS from a quick search.
- NTS as the default disincentivises any first-class threading story
- there's no significant advantage NTS has. It gets rid of a tiny bit of mutex locking or per-thread copying, but most of the other cost doesn't have to exist. Worst case performance cost of ZTS in php 8.5 was ~5%, will be ~1.5% in php 8.6, likely ~0.5% after my last open PRs. This doesn't have to stay the case - the last bits of performance penalty could be resolved if we convince the compiler to stop rederiving TLS addresses after function calls.
Generally, no large code changes are needed. Removing a lot of duplication in php-src is good.
Potential blockers
- The JIT doesn't work for ZTS builds on arm64 macOS.
- Thread unsafe extensions like ext-imap will continue working in the single-threaded execution of fpm. The only extension I'm aware of that doesn't support ZTS builds at all currently is new relics.
ZTS jit on arm64 macOS is the only part I couldn't do myself (don't have arm64 apple silicon at hand). Everything else I would implement myself.
I think it would really benefit the health of php distributions and evolution in the future. Given the small change surface for extension or build providers, and users, I would like to land the removal in PHP 9.0.
Best regards,
Marc Henderkes