Re: [Pre-RFC] Deprecating NTS and making ZTS the default build mode

From: Date: Sat, 11 Jul 2026 20:17:46 +0000
Subject: Re: [Pre-RFC] Deprecating NTS and making ZTS the default build mode
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-131872@lists.php.net to get a copy of this message
On Sat, 11 Jul 2026 at 17:57, Marc Henderkes <m@pyc.ac> wrote: > > 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: > 1. 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. > > 2. maintenance cost in php-src itself: ~420 #ifdef ZTS results and ~30 for #ifndef ZTS from a > quick search. > > 3. NTS as the default disincentivises any first-class threading story > > 4. 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 This sounds good. I'm just adding another blocker to the list for awareness: the fuzzer SAPI is currently configured to emit error at the configuration phase when ZTS is enabled.

« previous php.internals (#131872) next »