Skip to content

file: add range-level sparse file caching with hole punching#26

Open
achille-roussel wants to merge 2 commits into
mainfrom
sparse-file-cache
Open

file: add range-level sparse file caching with hole punching#26
achille-roussel wants to merge 2 commits into
mainfrom
sparse-file-cache

Conversation

@achille-roussel

Copy link
Copy Markdown
Contributor

Summary

  • Add platform-specific sparse file support (darwin/linux) with SEEK_HOLE, SEEK_DATA, and hole punching via F_PUNCHHOLE/fallocate
  • Track cached ranges individually in the LRU with a secondary index for efficient file-level operations (e.g., ETag invalidation)
  • When cache exceeds size limit, punch holes in sparse files to reclaim space while preserving other cached ranges
  • Add comprehensive tests for sparse file operations and range-level eviction

Test plan

  • go test ./file/... passes
  • TestPunchHole verifies hole punching reduces disk usage
  • TestRangeLevelEviction verifies range eviction punches holes instead of deleting files
  • Coverage at 81.8% with punchHole at 100%

🤖 Generated with Claude Code

@achille-roussel achille-roussel added the enhancement New feature or request label Jan 12, 2026
@achille-roussel achille-roussel self-assigned this Jan 12, 2026
@achille-roussel achille-roussel added the enhancement New feature or request label Jan 12, 2026

@spenczar spenczar left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the motivation of this change, and how will we verify it meets those goals?

@achille-roussel

Copy link
Copy Markdown
Contributor Author

I'm making this because overall this cache has been really helpful everywhere I added it, and I want to convert more use of in-memory cache to on-disk, but the file cache didn't support GetObject with ranges, so I know this will break when it starts reading parquet files.

On merge, this will be mostly a no-op, but I want to test it with our query engines. It will be a different pull request on other repositories to enable it.

@spenczar

Copy link
Copy Markdown
Contributor

@achille-roussel I still don't really understand, sorry... so this is in order to support range queries? Can you help me connect the dots on how hole punching (which is a new term to me) is related to range queries?

Sorry to be pushy on this, but I think this is the right new way to think about code review ;)

@achille-roussel

Copy link
Copy Markdown
Contributor Author

Let's just talk this through in our next 1:1, no rush :)

achille-roussel and others added 2 commits January 29, 2026 00:25
Implement fine-grained cache eviction using sparse files and hole punching.
Instead of evicting entire files, individual ranges can be evicted by
punching holes in the sparse cache file, reclaiming disk space while
preserving other cached ranges.

Key changes:
- Add platform-specific sparse file support (darwin/linux) with SEEK_HOLE,
  SEEK_DATA, and hole punching via F_PUNCHHOLE/fallocate
- Track cached ranges individually in the LRU with a secondary index for
  efficient file-level operations (e.g., ETag invalidation)
- Add comprehensive tests for sparse file operations and range-level eviction

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add test suite improvements for range-level sparse file caching:

Tests added to cache_test.go:
- TestSecondaryIndexConsistency: verify c.files index consistency
- TestEmptyFileCleanupAfterEviction: verify file cleanup on full eviction
- TestConcurrentRangeRequests: parallel goroutines requesting ranges
- TestOverlappingRangeRequests: overlapping range handling
- TestZeroByteObjectCaching: zero-byte object edge case
- TestRangeBeyondFileSize: range extending past object size
- TestCacheRehydrationWithSparseFiles: cache restart behavior
- TestBlockAlignmentDuringFetch: block alignment optimization
- TestMultipleFilesLRUEviction: LRU eviction across files
- TestCorruptedCacheMetadataRecovery: cache file deletion recovery
- TestCacheRevalidationWithBackendError: fail-open revalidation behavior

Tests added to sparse_test.go:
- TestDiskUsageAccuracy: verify diskUsage() accuracy
- TestHolePunchingReducesDiskUsage: verify hole punching reclaims space
- TestSparseFileWithMultipleHoles: alternating data/hole patterns

Add t.Parallel() to all tests for ~35% speedup (2.0s -> 1.3s).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants