|
what are the tradeoffs around speed, disk usage, isolation, cleanup, and CI behavior? |
Replies: 1 comment
|
kache trades a small, bounded per-compile overhead for large wins in reuse, disk dedup, and isolation without coupling. It pays off whenever builds repeat at all (worktrees, CI, incremental day-to-day work), which is almost always. SpeedWarm hits skip compilation entirely, and restore is hardlink or reflink, so materializing shared bytes is near-instant on modern filesystems. Reuse spans worktrees and, with the remote cache, whole CI fleets and teammates. The cost is modest and bounded: kache does a little extra work per compile to capture inputs precisely (a dep-info pre-pass for Rust, a preprocessor pass for C). On a first cold build that is a small tax, and it is repaid the moment anything is Disk usageThis is one of kache's strongest wins. The store is content-addressed, so identical artifacts dedup across crates, across worktrees, and across machines, and reflink restore means shared bytes are not physically copied at all. On the filesystems The store does hold blobs plus a small index, and on an older filesystem without reflink (for example ext4) restore falls back to a real copy. A size cap plus automatic GC keeps the whole thing bounded, so total footprint stays under control IsolationEach worktree keeps its own ./target/ and feels completely independent, while the cache is shared transparently underneath. That is the property a shared CARGO_TARGET_DIR cannot give you: it serializes builds on a single lock and can hand back One deliberate tradeoff worth knowing: kache shares whole-crate artifacts rather than Cargo incremental fragments, so it turns incremental off. For the common case (parallel worktrees, CI, switching branches) that is a clear win. The one workflow CleanupCleanup is automatic and centralized. Instead of hand-managing N target directories, you have one store that GC keeps under a size cap, using an LRU plus size-weighted score with a grace period that protects builds in flight, and it sweeps orphaned Today the policy is intentionally simple: one global pool governed by a max size. That is plenty for the common case, with finer-grained quotas (for example per language) as a natural next step. CI behaviorCI is where the remote cache shines. An S3-compatible store (AWS, Ceph, MinIO, R2) shares artifacts across runners and between CI and local, and because kache normalizes paths and env, keys converge across machines, so a fresh runner can hit a Two things worth setting up deliberately. First, a cold ephemeral runner has an empty local store, so its value comes from the remote tier, which is exactly what the remote cache is for. Second, a shared cache is a shared trust boundary, so the |
kache trades a small, bounded per-compile overhead for large wins in reuse, disk dedup, and isolation without coupling. It pays off whenever builds repeat at all (worktrees, CI, incremental day-to-day work), which is almost always.
Speed
Warm hits skip compilation entirely, and restore is hardlink or reflink, so materializing shared bytes is near-instant on modern filesystems. Reuse spans worktrees and, with the remote cache, whole CI fleets and teammates.
The cost is modest and bounded: kache does a little extra work per compile to capture inputs precisely (a dep-info pre-pass for Rust, a preprocessor pass for C). On a first cold build that is a small tax, and it is repaid the moment any…