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

The thumbnail decode semaphore, the transcode rayon pool, and the ffmpeg
video-thumbnail fan-out all sized from std::thread::available_parallelism(),
which honours CPU affinity but ignores the CFS bandwidth quota (--cpus /
cgroup cpu.max). Under a container quota they therefore permit one CPU-heavy
task per *host* core onto cores the scheduler can't grant — the same
over-subscription the runtime worker pool had.

Switch all three to common::runtime::effective_parallelism() (= min(affinity,
CFS quota)), and fix the doc comments that wrongly claimed available_parallelism
respects cgroup quotas. No change off-quota (effective == available there); the
env overrides (OXICLOUD_THUMBNAIL_DECODE_CONCURRENCY,
OXICLOUD_VIDEO_THUMBNAIL_CONCURRENCY) are unchanged.

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 08:46:24 +00:00
parent 7b26ff014c
commit 5629ba6200
3 changed files with 16 additions and 15 deletions
+3 -3
View File
@@ -363,9 +363,9 @@ impl AppServiceFactory {
if self.config.features.enable_video_thumbnails
&& FfmpegVideoFrameService::is_available(&ffmpeg_path)
{
let cpus = std::thread::available_parallelism()
.map(|n| n.get())
.unwrap_or(4);
// effective_parallelism respects the CFS quota (--cpus), not
// just affinity — so ffmpeg fan-out matches the real core budget.
let cpus = crate::common::runtime::effective_parallelism();
let concurrency = std::env::var("OXICLOUD_VIDEO_THUMBNAIL_CONCURRENCY")
.ok()
.and_then(|v| v.parse::<usize>().ok())