Skip to content

feat(hasher): add mmap path for Tier 3 hashing on large files (#7)#42

Closed
itsmessc wants to merge 3 commits into
Rakshat28:mainfrom
itsmessc:feat/mmap-tier3-hashing
Closed

feat(hasher): add mmap path for Tier 3 hashing on large files (#7)#42
itsmessc wants to merge 3 commits into
Rakshat28:mainfrom
itsmessc:feat/mmap-tier3-hashing

Conversation

@itsmessc

@itsmessc itsmessc commented May 3, 2026

Copy link
Copy Markdown

For files >= 1 MiB on Unix, full_hash now memory-maps the file and passes the mapped slice directly to blake3::hash(), eliminating the 128 KB userspace copy loop. Smaller files and non-Unix targets keep the existing BufReader path unchanged.

Also removes the dead sparse_hash() call in the scan worker whose return value was discarded, causing every file to be read twice.

  • Add memmap2 = 0.9 dependency
  • Add src/lib.rs to expose hasher for Criterion benchmarks
  • Add benches/hash_bench.rs: mmap vs buffered at 512 KiB/1 MiB/4 MiB/16 MiB
  • Add three unit tests in hasher.rs covering empty file, mmap/buffered agreement, and small-file correctness

Closes #7

saicharan-superagi and others added 2 commits May 3, 2026 18:21
…t28#7)

For files >= 1 MiB on Unix, full_hash now memory-maps the file and
passes the mapped slice directly to blake3::hash(), eliminating the
128 KB userspace copy loop. Smaller files and non-Unix targets keep
the existing BufReader path unchanged.

Also removes the dead sparse_hash() call in the scan worker whose
return value was discarded, causing every file to be read twice.

- Add memmap2 = 0.9 dependency
- Add src/lib.rs to expose hasher for Criterion benchmarks
- Add benches/hash_bench.rs: mmap vs buffered at 512 KiB/1 MiB/4 MiB/16 MiB
- Add three unit tests in hasher.rs covering empty file, mmap/buffered
  agreement, and small-file correctness

Closes Rakshat28#7

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e Cargo.lock

Items used by the binary (via its own mod hasher) and the benchmark
appear unused from the lib crate perspective. Suppress with targeted
#[allow(dead_code)] rather than a crate-wide gate.
Copilot AI review requested due to automatic review settings May 3, 2026 13:21

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a Unix-only mmap fast path for large-file hashing, exposes the hashing module through a new library target for Criterion benchmarks, and removes an unnecessary extra hash read in the scan pipeline. It fits into the codebase by optimizing the Tier 3/full-hash path used during dedupe/scan while adding benchmark and unit-test coverage around the new hasher behavior.

Changes:

  • Add an mmap-based implementation path to hasher::full_hash for files at or above 1 MiB on Unix.
  • Remove the discarded sparse_hash() call from the scan worker so candidate files are no longer read twice.
  • Add a library target, benchmarking harness, and hasher unit tests to compare and validate buffered vs. mmap hashing.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/main.rs Simplifies scan worker hashing by removing the unused sparse_hash() call.
src/lib.rs Adds a library target surface so benches can import hashing code.
src/hasher.rs Implements the mmap threshold path, adds buffered benchmark helper, and adds unit tests.
benches/hash_bench.rs Adds Criterion benchmarks comparing mmap and buffered hashing across file sizes.
Cargo.toml Adds memmap2, registers the benchmark target, and adds Criterion dev dependency.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/hasher.rs Outdated

/// Always uses the 128 KB BufReader loop, regardless of file size.
/// Exposed for benchmarking so the mmap and buffered paths can be compared directly.
pub(crate) fn full_hash_buffered(path: &Path) -> Result<Hash> {
Comment thread src/hasher.rs Outdated
Comment on lines +48 to +59
#[cfg(unix)]
if len >= MMAP_THRESHOLD {
// SAFETY: The file may be modified by another process while it is mapped.
// bdstorage operates on user-owned files not expected to be concurrently
// written. In the worst case a concurrent write produces a stale hash that
// the next scan will correct. The mapped region is used as a read-only
// &[u8] slice by BLAKE3, so no Rust memory-safety invariant is violated.
let mmap = unsafe { memmap2::Mmap::map(&file) }
.with_context(|| format!("mmap file {:?}", path))?;
return Ok(blake3::hash(&mmap[..]).into());
}

Comment thread src/hasher.rs Outdated
Comment on lines +72 to +73
/// Always uses the 128 KB BufReader loop, regardless of file size.
/// Exposed for benchmarking so the mmap and buffered paths can be compared directly.
Comment thread src/hasher.rs Outdated
Comment on lines +55 to +57
let mmap = unsafe { memmap2::Mmap::map(&file) }
.with_context(|| format!("mmap file {:?}", path))?;
return Ok(blake3::hash(&mmap[..]).into());
- pub(crate) -> pub on full_hash_buffered so Criterion bench (external
  crate) can import it through bdstorage::hasher
- fall through to chunked-read if Mmap::map fails instead of returning
  an error, preventing silent file drops on unsupported filesystems
- update SAFETY comment to mention SIGBUS risk from concurrent truncation
- fix doc comment: 'BufReader loop' -> '128 KB chunked read loop'
@Rakshat28 Rakshat28 self-requested a review May 3, 2026 17:15
@Rakshat28

Rakshat28 commented May 9, 2026

Copy link
Copy Markdown
Owner

@itsmessc The PR is failing CI test, also include updated benchmark numbers (and steps to replicate them).

@Rakshat28

Copy link
Copy Markdown
Owner

Hey @itsmessc @saicharan-superagi , just checking in on this! It looks like the integration tests are failing. Let us know if you need any help debugging this, otherwise, we might need to close this PR in a few days to keep the queue tidy.

@itsmessc

Copy link
Copy Markdown
Author

I will check with that

@Rakshat28 Rakshat28 closed this May 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Evaluate Memory-Mapped I/O for Tier 3

4 participants