From be0f470239b7cafed2c0f98d5f30b7d8eec765c0 Mon Sep 17 00:00:00 2001 From: David Montero Crespo Date: Thu, 20 Aug 2026 06:28:46 +0200 Subject: [PATCH] perf(compile): rebalance disk from build variants to ccache Measured on staging: 46 per-variant build trees held 25 GB - each one a full copy of the same ESP-IDF component objects - while ccache, the cache that serves EVERY target and variant, was capped at 8 GB and permanently full: 99.97% of its limit, 153 evictions, 47% lifetime hit rate. Objects were being thrown out before they could be reused, so builds recompiled work they had already done. Variant cap 12 -> 6 and ccache 8G -> 20G. The asymmetry is deliberate: an evicted variant dir rebuilds quickly FROM ccache, whereas a ccache miss recompiles from source. Pruning the cold variants freed 8 GB on the staging box (88% -> 84% disk) before the larger cache can grow into it. --- Dockerfile.standalone | 2 +- backend/app/services/espidf_compiler.py | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Dockerfile.standalone b/Dockerfile.standalone index 2f6e2d07..c5478915 100644 --- a/Dockerfile.standalone +++ b/Dockerfile.standalone @@ -308,7 +308,7 @@ ENV CCACHE_NOHASHDIR=1 # runtime by the volume mount. ccache reads CCACHE_MAXSIZE / CCACHE_COMPRESS # / CCACHE_COMPRESSLEVEL on every invocation and they override any conf-file # value, so the cap actually applies at runtime. -ENV CCACHE_MAXSIZE=8G +ENV CCACHE_MAXSIZE=20G ENV CCACHE_COMPRESS=1 ENV CCACHE_COMPRESSLEVEL=6 RUN mkdir -p /var/cache/ccache /var/lib/velxio-build /root/Arduino diff --git a/backend/app/services/espidf_compiler.py b/backend/app/services/espidf_compiler.py index ea390169..6c263f28 100644 --- a/backend/app/services/espidf_compiler.py +++ b/backend/app/services/espidf_compiler.py @@ -219,7 +219,13 @@ def _run_with_streaming( # coldest. Each variant is a full ESP-IDF build tree (~240 MB). Distinct # variants = distinct (board options x resolved library set). The global ccache # means an evicted-then-rebuilt variant warms up in seconds. -_MAX_BUILD_VARIANTS = 12 +# Was 12. Each variant is a FULL ~1 GB build tree holding its own copies of +# the same ESP-IDF component objects, so 46 of them had grown to 25 GB while +# ccache - the cache that actually serves EVERY target and variant - sat +# capped at 8 GB, permanently full (99.97%, 153 evictions, 47% hit rate). +# Fewer trees, a bigger shared cache: a variant that gets evicted rebuilds +# quickly FROM ccache, but a ccache miss recompiles from source. +_MAX_BUILD_VARIANTS = 6 def _evict_cold_variants(target_dir: Path, keep: int) -> None: