From 061921528481f8fb6fe2c15b1f1197f77e6954e5 Mon Sep 17 00:00:00 2001 From: Lev Brouk Date: Wed, 27 May 2026 23:39:29 -0700 Subject: [PATCH 1/2] perf(build): cache resolved Diff per BuildId within File.ReadAt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A single ReadAt call can iterate the mapping loop many times after post-dedup memfile fragmentation (4 KiB-granular mappings across a 2 MiB hugepage fault). Each iteration hit DiffStore.Get → ttlcache.Get, taking the shared ttlcache mutex per mapping. Stack-allocated fixed-cap slices (16 entries) + linear scan cover the typical unique BuildIds in a chain. Allocation-free regardless of read size; eviction race handled by dropping the stale entry on ErrCacheClosed and re-resolving. --- .../orchestrator/pkg/sandbox/build/build.go | 50 +++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/packages/orchestrator/pkg/sandbox/build/build.go b/packages/orchestrator/pkg/sandbox/build/build.go index 196436bb79..e527b92425 100644 --- a/packages/orchestrator/pkg/sandbox/build/build.go +++ b/packages/orchestrator/pkg/sandbox/build/build.go @@ -55,9 +55,20 @@ func (b *File) SwapHeader(h *header.Header) { } func (b *File) ReadAt(ctx context.Context, p []byte, off int64) (n int, err error) { + // Cache some resolved Diffs per BuildId for the duration of one ReadAt to avoid + // hitting the DiffStore TTL cache (and its mutex) on every iteration. + const buildCacheSize = 16 + var ( + underlyingIDs [buildCacheSize]uuid.UUID + underlyingDiffs [buildCacheSize]Diff + cacheIDs = underlyingIDs[:0] + cacheDiffs = underlyingDiffs[:0] + ) + for n < len(p) { h := b.Header() + // Find out what build and ranghe we need to read, from mappings. mappedToBuild, err := h.GetShiftedMapping(ctx, off+int64(n)) if err != nil { return 0, fmt.Errorf("failed to get mapping: %w", err) @@ -94,17 +105,50 @@ func (b *File) ReadAt(ctx context.Context, p []byte, off int64) (n int, err erro size := b.buildFileSize(h, mappedToBuild.BuildId) ft := h.GetBuildFrameData(mappedToBuild.BuildId) - mappedBuild, err := b.getBuild(ctx, mappedToBuild.BuildId, size, ft.CompressionType()) - if err != nil { - return 0, fmt.Errorf("failed to get build: %w", err) + + // Find the build in the caches. + var mappedBuild Diff + hitIdx := -1 + for i, id := range cacheIDs { + if id == mappedToBuild.BuildId { + mappedBuild = cacheDiffs[i] + hitIdx = i + + break + } + } + if mappedBuild == nil { + mappedBuild, err = b.getBuild(ctx, mappedToBuild.BuildId, size, ft.CompressionType()) + if err != nil { + return 0, fmt.Errorf("failed to get build: %w", err) + } + if len(cacheIDs) < cap(cacheIDs) { + cacheIDs = append(cacheIDs, mappedToBuild.BuildId) + cacheDiffs = append(cacheDiffs, mappedBuild) + } } + // Read from that build, and handle the various retries. buildN, err := mappedBuild.ReadAt(ctx, p[n:int64(n)+readLength], int64(mappedToBuild.Offset), ft, ) if err != nil { + // Cache may have evicted+closed the Diff between resolve and ReadAt; + // drop the stale entry and re-resolve on the next iteration. + var closed *block.CacheClosedError + if errors.As(err, &closed) { + if hitIdx >= 0 { + last := len(cacheIDs) - 1 + cacheIDs[hitIdx] = cacheIDs[last] + cacheDiffs[hitIdx] = cacheDiffs[last] + cacheIDs = cacheIDs[:last] + cacheDiffs = cacheDiffs[:last] + } + + continue + } if retry, swapErr := b.retryOnTransition(ctx, err); retry { continue } else if swapErr != nil { From 84bfc9dff13768f989520a27c13e34d910ee5f2c Mon Sep 17 00:00:00 2001 From: Lev Brouk Date: Thu, 28 May 2026 08:48:40 -0700 Subject: [PATCH 2/2] PR feedback --- packages/orchestrator/pkg/sandbox/build/build.go | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/orchestrator/pkg/sandbox/build/build.go b/packages/orchestrator/pkg/sandbox/build/build.go index e527b92425..605a103b21 100644 --- a/packages/orchestrator/pkg/sandbox/build/build.go +++ b/packages/orchestrator/pkg/sandbox/build/build.go @@ -125,6 +125,7 @@ func (b *File) ReadAt(ctx context.Context, p []byte, off int64) (n int, err erro if len(cacheIDs) < cap(cacheIDs) { cacheIDs = append(cacheIDs, mappedToBuild.BuildId) cacheDiffs = append(cacheDiffs, mappedBuild) + hitIdx = len(cacheIDs) - 1 } }