P1: no global cap on concurrent image processing — unbounded memory under load #64
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Verified against
mainat61f42e6. This is the "rate limit global concurrent upstream fetches to prevent resource exhaustion" P1 item fromTODO.md, but the survey found the processing side is the larger risk, so scoping the issue around both.There is no global concurrency limiter anywhere in the request path. What exists is
MaxConnectionsPerHost, a per-upstream-host semaphore (internal/httpfetcher/httpfetcher.go:154-165), which does nothing to bound total in-flight work across many hosts.Per cache miss, the following are held in memory simultaneously:
MaxResponseSize, 50 MiB) atinternal/imageprocessor/imageprocessor.go:142-151internal/imgcache/service.go:254internal/imgcache/service.go:323With N concurrent misses that is N x (source + raster + output) resident, with no ceiling. Against the 1k-5k req/s target in
README.md:49, a modest burst of misses across distinct hosts is an OOM, and this is reachable by anyone who can produce valid URLs.vips.Startup(nil)(imageprocessor.go:22) also accepts libvips' default concurrency and cache settings rather than choosing them deliberately.Definition of done
vips.Startupconfiguration (concurrency, operation cache) instead ofnil, with the chosen values explained in the PR.make checkgreen (the suite runs with-raceas of #55).Related
Service.Get.