Skip to content

feat: num_threads counts the threads left for regular requests - #2660

Open
nicolas-grekas wants to merge 2 commits into
php:mainfrom
nicolas-grekas:regular-threads
Open

nicolas-grekas wants to merge 2 commits into
php:mainfrom
nicolas-grekas:regular-threads

Conversation

@nicolas-grekas

@nicolas-grekas nicolas-grekas commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

num_threads is a total today and worker threads are part of it, so sizing a server means doing the subtraction by hand: give a worker four more threads and four fewer are left for the requests no worker serves. Nothing says so either, config.md describes it as "the number of PHP threads to start" and only an error message mentions the subtraction.

It now counts the threads for those requests, and the worker threads come on top of it. max_threads keeps its meaning, the limit on everything the process runs, which is what the memory heuristic of auto bounds, and every worker keeps its own num and max_threads. So nothing is added to the configuration, and the num_threads must be greater than the number of worker threads error goes away with the arithmetic that caused it.

{
	frankenphp {
		num_threads 4 # threads for the requests no worker serves
		max_threads auto

		worker {
			file jobs.php
			num 8 # on top, and no longer at the expense of the 4
		}
	}
}

Defaults are unchanged: without num_threads, a server still starts what is left of 2x the CPUs once the workers have their threads, one at the very least.

What changes for an existing configuration: one that sets num_threads with workers declared starts more threads than before, extension workers included since they are worker threads too. Where max_threads is set below num_threads plus the worker threads, startup now fails with an error naming the three numbers, where it booted before with the workers inside num_threads: that is the break, and the one to mention in the release notes. Conversely, a configuration that was rejected for a num_threads at or below its worker threads now boots. The startup line reports total_threads and worker_threads so the totals are visible, and the tests this breaks in the repo are exactly the ones that had written a total: three Caddyfiles and a scaling test that now say one thread less.

Replaces the num_regular_threads / max_regular_threads of the first version of this PR, after @AlliBalliBaba pointed out that reinterpreting the existing option beats adding two more, which I agree with: this ends with fewer settings than we have today rather than more.

@AlliBalliBaba

Copy link
Copy Markdown
Contributor

I know I suggested this, at the same time, I really dislike having even more configurations for thread numbers 😅 . But maybe it's the right way forward.

I wonder if we could just somehow reinterpret num_threads as num_regular_threads with minimal BC break, but not sure that's possible.

@nicolas-grekas nicolas-grekas changed the title feat: num_regular_threads and max_regular_threads feat: num_threads counts the threads left for regular requests Sep 20, 2026
@nicolas-grekas

Copy link
Copy Markdown
Contributor Author

Done, the PR does that now: no new options, num_threads counts the threads for the requests no worker serves and the worker threads come on top, max_threads still bounds everything the process runs. Defaults don't move, and the num_threads must be greater than the number of worker threads error goes away with the arithmetic behind it, so we end with less configuration than today rather than more.

The BC break is a single behaviour: a config that sets num_threads with workers declared starts more threads than before, bounded by max_threads where it's set. In the repo it hit exactly three test Caddyfiles that had written a total, they now say num_threads 1. The startup line reports total_threads and worker_threads so nobody has to infer it.

WDYT?

num_threads is a total today and worker threads are part of it, so sizing
a server means subtracting them by hand: give a worker four more threads
and four fewer are left for the requests no worker serves. Nothing says so
either, the docs describe num_threads as "the number of PHP threads to
start" and only an error message mentions the subtraction.

It now counts the threads for those requests, and the worker threads come
on top of it. max_threads keeps its meaning, the limit on everything the
process runs, which is what the memory heuristic of auto bounds, and every
worker keeps its own num and max_threads. Nothing is added to the
configuration and the "num_threads must be greater than the number of
worker threads" error goes away with the arithmetic that caused it.

Defaults are unchanged: without num_threads a server still starts what is
left of 2x the CPUs once the workers have their threads, one at the very
least. A configuration that sets num_threads with workers declared starts
more threads than before, up to max_threads where it is set; the startup
line reports total_threads and worker_threads so the totals are visible.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants