Skip to content

Share one pixi package cache across containers: --mount + PIXI_CACHE_DIR from workspace_up #232

Description

@blooop

Graduated from map blooop/dotfiles#13's pixi-cache fog item after a measured investigation (2026-08-15). Owner: devlaunch alone — dotfiles need no edit, no repo's devcontainer.json is involved.

Measured case

The container profile's real workload is 23 pixi-global envs. pixi global sync with a scratch PIXI_CACHE_DIR/PIXI_HOME:

  • COLD (empty cache): 62–113 s, 1.2 GB downloaded
  • WARM (fresh PIXI_HOME, pre-warmed cache): 18–28 s
  • NO-OP (envs present): 0.6 s

So a shared cache saves ~40–90 s and 1.2 GB of network per cold container, compounding with wayfinder's N-containers-per-map pattern. wayfinder#39 already names dotfiles/tool provisioning the dominant cold-launch cost; this is that cost's biggest slice.

Facts the design leans on (verified)

  • The shareable part is exactly ~/.cache/rattler/cache (content-addressed pkgs/, per-package .lock files). Envs and trampolines are prefix-baked and must stay per-container.
  • PIXI_CACHE_DIR is honored and wins over RATTLER_CACHE_DIR (pixi 0.76.1, verified via pixi info) — so the dotfiles install.sh's conditional RATTLER_CACHE_DIR fallback is harmlessly overridden; an inherited env var is consumed as-is with no dotfiles change.
  • Concurrency: safe. Two simultaneous pixi global sync runs sharing one fresh cache (separate PIXI_HOMEs) → both exit 0, all binaries work. rattler locks per package. The known bug (Error: failed to collect prefix records during concurrent execution on HPC (SLURM + Lustre) prefix-dev/pixi#5476) is a shared env prefix, not a shared cache — it argues for exactly this split. Never share PIXI_HOME/envs across containers.
  • devpod up takes --mount type=bind,source=…,target=… and --workspace-env/--dotfiles-script-env first-class; workspace_up() (dl.py ~3495) already appends --init-env/--dotfiles/--workspace-env-file, so this is two more entries at the one argv seam.
  • uid: containers write as vscode (uid 1000 = host user here), but that is not guaranteed for other remoteUsers — hence a dedicated host dir (~/.cache/devlaunch/pixi), never the host's real ~/.cache/rattler/cache; this also keeps a host pixi clean cache from yanking packages under a live container, and makes GC trivially safe (rm -rf of a pure cache).
  • Cross-filesystem hardlink fallback is a copy: measured 20.7 s for 1.2 GB — still far cheaper than downloading.

Done when

  1. workspace_up() appends --mount type=bind,source=$HOME/.cache/devlaunch/pixi,target=/home/vscode/.cache/devlaunch-pixi, --workspace-env PIXI_CACHE_DIR=/home/vscode/.cache/devlaunch-pixi, and the matching --dotfiles-script-env (the dotfiles install script is the consumer).
  2. Spawn-count/argv pins updated at the same seam the existing up-args tests use.
  3. Live acceptance: two back-to-back dl launches of different repos on a clean scratch cache — the second one's pixi global sync finishes <30 s with no network fetch; two dl up in parallel leave both containers with working rg/go/jq.
  4. README notes the shared cache dir and that deleting it is always safe.

Recorded alternatives / falsification

  • Not chosen: sharing a whole PIXI_HOME volume (~0.6 s installs) — puts concurrent syncs on one prefix tree, which is exactly pixi#5476. Do not.
  • Falsification condition: if the base image ever bakes the pixi manifest in, the delta collapses toward the 0.6 s no-op number and this mount stops earning its keep — reopen then.
  • GC story for the dedicated dir is deliberately out of scope (it is a pure cache; rm -rf is the GC).

This ticket was generated by AI during investigation follow-through; measurements above were taken live on 2026-08-15.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions