Re: [Pre-RFC] Deprecating NTS and making ZTS the default build mode
| From: | Calvin Buckley | Date: | Sat, 11 Jul 2026 21:08:51 +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-131873@lists.php.net to get a copy of this message | ||
At work, I maintain a PHP distribution on a non-mainstream platform shipping NTS. No real reason
other than that's the way we've always built it; there's no urgency to switch since
99.9% of the users aren't using threaded SAPIs. I can try ZTS builds and see what (or really if
it) breaks down for me.
FWIW as an RM, we run the basic tests for a release in both NTS and ZTS, so any low-hanging fruit
with CLI/CGI should be caught at least.
> On Jul 11, 2026, at 12:52 PM, 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