The `[thread]` section sets how many worker threads bees runs and how aggressively it ramps up under system load.
+`thread-min`, `thread-max`, and `loadavg-target` are [size values](config-format.md#size-values): they accept arithmetic expressions, `min()`/`max()`/`ceil()`, and the substitution variables `${NPROC}` (the number of logical CPUs) and `${THREAD_FACTOR}` (the `thread-factor` value below). This is what puts the CPU-relative arithmetic in your control — for example `thread-max = min(8, ${NPROC})` or `loadavg-target = ${NPROC}`. `thread-min` and `thread-max` are rounded to integers; `loadavg-target` keeps its fractional value (e.g. `0.5`).
+
* **`thread-min`** *(legacy `-G`)*
Minimum number of worker threads bees keeps active, regardless of load-based throttling.
Default: `0`.
* **`thread-max`** *(legacy `-c`)*
- Hard cap on worker threads. Leave **blank** to remove this explicit cap; the count then depends only on `thread-factor` (and `thread-min`).
- If both `thread-factor` and `thread-max` are set, the result is **limited** to `thread-max`.
+ Number of worker threads to run. It means exactly what the expression evaluates to; it is **not** silently combined with `thread-factor`.
+ Default: `max(1, ceil(${NPROC} * ${THREAD_FACTOR}))` — i.e. one thread per CPU scaled by `thread-factor`, rounded up, never below 1.
+ To cap a CPU-relative count, write the `min()` yourself, e.g. `min(8, ceil(${NPROC} * ${THREAD_FACTOR}))`. The legacy `-c N` option overrides this with an exact count of `N` threads — its historical behaviour: `thread-factor` is ignored and values above the CPU count are honoured (oversubscription).
* **`thread-factor`** *(legacy `-C`)*
- Ratio (multiplier) applied to detected CPU threads (logical CPUs). The result is **rounded up**.
- Accepts any ratio format (see [Configuration File Format Reference](config-format.md)).
+ Threads per logical CPU. It is not consumed directly; it is exposed to the expressions above as `${THREAD_FACTOR}` (the default `thread-max` multiplies it by `${NPROC}` and rounds up with `ceil()`).
+ Accepts any ratio format (see [Configuration File Format Reference](config-format.md)); the value is normalised to a number before substitution.
Default: `1.0`.
* **`loadavg-target`** *(legacy `-g`)*
Controls load-based ramping.
- * `0` disables loadavg throttling (bees uses only the static count from `thread-min`/`thread-factor`/`thread-max`).
- * `>0` makes bees start with the `thread-min` number of workers and then add more until either the 1-minute load average approaches the target or the limit from `thread-factor`/`thread-max` is reached.
+ * `0` disables loadavg throttling (bees uses only the static count from `thread-min`/`thread-max`).
+ * `>0` makes bees start with the `thread-min` number of workers and then add more until either the 1-minute load average approaches the target or the `thread-max` limit is reached.
* **`task-queue-max`**
Maximum number of extent-scan tasks the crawler will queue at once before backpressuring itself, expressed as a count of in-flight `Task` objects. Larger values increase parallelism and memory use; smaller values reduce wasted work after a restart by keeping fewer extents in flight.
| -------- | ------------- |
| `$$` | literal `$` character. |
| `${BASENAME}` | last path component of `${ROOT}`. |
+| `${FS_BYTES}` | total capacity of the target filesystem, in bytes. |
| `${LABEL}` | the label of the target filesystem. |
+| `${NPROC}` | the number of logical CPUs (at least 1). |
+| `${RAM_BYTES}` | total installed physical RAM, in bytes. |
| `${ROOT}` | the canonical (`realpath`) path to the root of the target filesystem. |
+| `${THREAD_FACTOR}` | the `[thread]` `thread-factor` value, normalised to a number. |
| `${UUID}` | the target filesystem's UUID in `aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee` notation. |
Any `/` characters in `LABEL` are replaced with `_`.
Whitespace around the operator is optional (`128K+1` and `128K + 1`
are equivalent). The `-` operator rejects values that would underflow.
+Size values are full arithmetic expressions, evaluated in `double` and
+returned as a non-negative integer:
+
+ * operators `+`, `-`, `*`, `/` with the usual precedence, and `(` `)` grouping
+ * a `%` suffix divides by 100 (e.g. `${RAM_BYTES} * 5%`)
+ * functions `min(a, b)`, `max(a, b)`, and `ceil(a)`
+ * [interpolated variables](#value-string-interpolations) such as
+ `${RAM_BYTES}`, `${FS_BYTES}`, `${NPROC}`, and `${THREAD_FACTOR}`
+
+For example, the default hash-table size is
+`min(${RAM_BYTES} / 16, ${FS_BYTES} / 16384)` and the default worker count is
+`max(1, ceil(${NPROC} * ${THREAD_FACTOR}))`.
+
### Duration values
A duration value is one or more whitespace-separated or adjacent
* `--thread-count COUNT` or `-c`
- Specify maximum number of worker threads. Overrides `--thread-factor`
- (`-C`), default/autodetected values, and the hardcoded thread limit.
+ Set the number of worker threads to exactly `COUNT`, overriding the default
+ `thread.thread-max` expression (and therefore `--thread-factor`). Values
+ larger than the CPU count are honoured, so this can oversubscribe CPUs.
* `--thread-factor FACTOR` or `-C`
- Specify ratio of worker threads to detected CPU cores. Overridden by
- `--thread-count` (`-c`).
+ Specify ratio of worker threads to detected CPU cores. This is the
+ `${THREAD_FACTOR}` substitution used by the default `thread.thread-max`
+ expression, `max(1, ceil(${NPROC} * ${THREAD_FACTOR}))`. It has no effect
+ when `--thread-count` (`-c`) sets an explicit count.
Default is 1.0, i.e. 1 worker thread per detected CPU. Use values
below 1.0 to leave some cores idle, or above 1.0 if there are more