Revert "perf(pools): size image/rayon pools to the CFS quota"

This reverts the image-pool migration (commit 5629ba6). The bench
(bench_pool_concurrency / POOL-CONCURRENCY.md) measured the one pool it could
isolate — the thumbnail decode semaphore — and found flat throughput, p99 AND
peak RSS (137 MiB) from K=1..16: shrink-on-load already makes each decode
RAM-cheap, so sizing it to the CFS quota gains nothing measurable. Adding code
without a measured benefit isn't worth it.

Kept: the effective_parallelism() helper (it has a *measured* win in the Tokio
runtime — benches/RUNTIME.md) and the benchmark itself (reusable). The ffmpeg
video fan-out has a plausible a-priori case (one OS process per permit) but is
left as a future, deliberately-measured change rather than shipped on
speculation. Doc updated to record the decision.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JG5yYZ9s868mJwqT2Qz7ez
This commit is contained in:
Claude
2026-06-22 09:04:37 +00:00
parent 013090a14e
commit 18781022be
4 changed files with 28 additions and 25 deletions
@@ -31,14 +31,13 @@ pub const MAX_TRANSCODE_SIZE: u64 = 5 * 1024 * 1024;
/// Minimum number of threads in the dedicated transcoding pool
const MIN_TRANSCODE_THREADS: usize = 2;
/// Compute the number of transcoding threads: half the available CPUs, with a
/// floor of `MIN_TRANSCODE_THREADS`. Sized by
/// [`effective_parallelism`](crate::common::runtime::effective_parallelism),
/// which respects CPU affinity **and** the CFS quota (Docker/K8s `--cpus`) —
/// unlike bare `available_parallelism()`, which ignores the quota and would
/// over-size this CPU-bound pool under a container limit.
/// Compute the number of transcoding threads: half the available CPUs,
/// with a floor of `MIN_TRANSCODE_THREADS`. `available_parallelism()`
/// respects cgroup limits (Docker/K8s) and CPU affinity masks.
fn transcode_thread_count() -> usize {
let cpus = crate::common::runtime::effective_parallelism();
let cpus = std::thread::available_parallelism()
.map(|n| n.get())
.unwrap_or(MIN_TRANSCODE_THREADS);
(cpus / 2).max(MIN_TRANSCODE_THREADS)
}
@@ -107,11 +107,8 @@ const STREAM_TO_TEMP_TIMEOUT: Duration = Duration::from_secs(120);
/// concurrency was halved to keep peak RAM in check. Decodes are now DCT-shrunk
/// to the thumbnail size (~18–25 MB regardless of source resolution), so the RAM
/// ceiling no longer forces throttling and we can saturate every core. Override
/// with `OXICLOUD_THUMBNAIL_DECODE_CONCURRENCY`. Sized by
/// [`effective_parallelism`](crate::common::runtime::effective_parallelism),
/// which respects CPU affinity **and** the CFS quota (`--cpus`) — so under a
/// container quota we don't over-permit concurrent CPU-heavy decodes onto cores
/// the scheduler can't give us.
/// with `OXICLOUD_THUMBNAIL_DECODE_CONCURRENCY`. `available_parallelism()`
/// respects cgroup limits (Docker/K8s) and CPU affinity masks.
fn max_concurrent_decodes() -> usize {
if let Some(n) = std::env::var(DECODE_CONCURRENCY_ENV)
.ok()
@@ -120,7 +117,10 @@ fn max_concurrent_decodes() -> usize {
{
return n;
}
crate::common::runtime::effective_parallelism().max(2)
let cpus = std::thread::available_parallelism()
.map(|n| n.get())
.unwrap_or(4);
cpus.max(2)
}
/// Thumbnail service for generating and caching image thumbnails