Skip to content

feat: cacheless hamt iteration - #2216

Merged
LesnyRumcajs merged 10 commits into
filecoin-project:masterfrom
hanabi1224:hamt/for_each_cacheless
Feb 26, 2026
Merged

feat: cacheless hamt iteration#2216
LesnyRumcajs merged 10 commits into
filecoin-project:masterfrom
hanabi1224:hamt/for_each_cacheless

Conversation

@hanabi1224

@hanabi1224 hanabi1224 commented Sep 4, 2025

Copy link
Copy Markdown
Contributor

(Simliar to #2189)
This PR adds HamtImpl::for_each_cacheless and StateTree::for_each_cacheless to reduce memory usage for iterating over a large hamt, to address #2215 (comment)

cargo bench shows no significant difference between for_each and for_each_cacheless

HAMT for_each function  time:   [108.24 µs 108.70 µs 109.19 µs]
Found 4 outliers among 100 measurements (4.00%)
  4 (4.00%) high mild

HAMT for_each_cacheless function
                        time:   [106.85 µs 107.63 µs 108.58 µs]
Found 2 outliers among 100 measurements (2.00%)
  1 (1.00%) high mild
  1 (1.00%) high severe

@github-project-automation github-project-automation Bot moved this to 📌 Triage in FilOz Sep 4, 2025
@codecov-commenter

codecov-commenter commented Sep 4, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.64516% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.59%. Comparing base (b5883f4) to head (aeaa05b).
⚠️ Report is 4 commits behind head on master.

Files with missing lines Patch % Lines
fvm/src/state_tree.rs 0.00% 10 Missing ⚠️
ipld/hamt/src/node.rs 95.45% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2216      +/-   ##
==========================================
+ Coverage   77.58%   77.59%   +0.01%     
==========================================
  Files         147      147              
  Lines       15789    15851      +62     
==========================================
+ Hits        12250    12300      +50     
- Misses       3539     3551      +12     
Files with missing lines Coverage Δ
ipld/hamt/src/hamt.rs 97.26% <100.00%> (+0.10%) ⬆️
ipld/hamt/src/hash_algorithm.rs 73.33% <ø> (ø)
ipld/hamt/src/lib.rs 100.00% <ø> (ø)
ipld/hamt/src/node.rs 91.74% <95.45%> (+0.44%) ⬆️
fvm/src/state_tree.rs 72.61% <0.00%> (-3.15%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@hanabi1224
hanabi1224 marked this pull request as ready for review September 4, 2025 12:31
fn hash<X>(key: &X) -> HashedKey
where
X: Hash,
X: Hash + ?Sized,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

To fix a clippy warning

@hanabi1224 hanabi1224 self-assigned this Sep 5, 2025
@BigLep BigLep moved this from 📌 Triage to 🔎 Awaiting Review in FilOz Sep 8, 2025
Comment thread fvm/src/state_tree.rs
Ok(())
}

pub fn for_each_cacheless<F>(&self, mut f: F) -> anyhow::Result<()>

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.

Docs?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

Comment thread ipld/hamt/src/hamt.rs

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.

Changelog entry?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@LesnyRumcajs

Copy link
Copy Markdown
Contributor

All in all, LGTM, but I'll let @rvagg have a final say here, my HAMT-fu is not that strong.

@BigLep
BigLep requested a review from Copilot September 16, 2025 05:24

Copilot AI 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.

Pull Request Overview

This PR adds cacheless iteration functionality to HAMT (Hash Array Mapped Trie) to reduce memory usage when iterating over large HAMTs. The primary addition is for_each_cacheless methods that avoid caching nodes during iteration, which can be more memory-efficient for one-time traversals.

  • Implements for_each_cacheless methods for both HamtImpl and StateTree
  • Adds comprehensive tests for the new cacheless iteration functionality
  • Includes benchmarks comparing performance between cached and cacheless iteration

Reviewed Changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
ipld/hamt/tests/hamt_tests.rs Adds comprehensive test suite for for_each_cacheless functionality and refactors existing test infrastructure
ipld/hamt/src/pointer.rs Implements Clone trait for Pointer enum to support cacheless iteration
ipld/hamt/src/node.rs Implements Clone trait for Node and adds core for_each_cacheless iteration logic
ipld/hamt/src/lib.rs Adds Clone trait to KeyValuePair struct to support cloning operations
ipld/hamt/src/hash_algorithm.rs Minor refactor to parameter order for Identity::hash method
ipld/hamt/src/hamt.rs Adds public for_each_cacheless method to the main HAMT API
ipld/hamt/benches/hamt_benchmark.rs Adds benchmark for for_each_cacheless and refactors existing benchmarks
ipld/hamt/Cargo.toml Adds itertools dependency for test utilities
fvm/src/state_tree.rs Adds for_each_cacheless method to StateTree API

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment thread ipld/hamt/src/node.rs Outdated
}
IterItem::Borrowed(Pointer::Dirty(node)) => stack.push(node.pointers.iter().into()),
IterItem::Owned(Pointer::Dirty(node)) => {
stack.push(node.pointers.clone().into_iter().into())

Copilot AI Sep 16, 2025

Copy link

Choose a reason for hiding this comment

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

The clone() call here creates an unnecessary copy of the entire pointers vector. Consider restructuring to avoid this clone operation, as it defeats the memory efficiency purpose of the cacheless iteration.

Suggested change
stack.push(node.pointers.clone().into_iter().into())
stack.push(node.pointers.into_iter().into())

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

Comment thread ipld/hamt/src/hamt.rs
/// map.set(4, 2).unwrap();
///
/// let mut total = 0;
/// map.for_each_cacheless(|_, v: &u64| {

Copilot AI Sep 16, 2025

Copy link

Choose a reason for hiding this comment

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

The type annotation in the example should be &usize to match the generic type used in the example setup, not &u64.

Suggested change
/// map.for_each_cacheless(|_, v: &u64| {
/// map.for_each_cacheless(|_, v: &usize| {

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@hanabi1224

hanabi1224 commented Oct 23, 2025

Copy link
Copy Markdown
Contributor Author

Hey @LesnyRumcajs @rvagg I have addressed all outstanding comments and all CI checks are green, please take another look.

@LesnyRumcajs LesnyRumcajs 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.

LGTM, but I'll let @rvagg make a final call. As mentioned earlier, my HAMT-fu is weak. :)

@ZenGround0 ZenGround0 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.

This LGTM. It's nice you are getting the same ordering but that's probably more than you need anyway since HAMTs are inherently unordered.

Comment thread ipld/hamt/src/hamt.rs
/// map.set(4, 2).unwrap();
///
/// let mut total = 0;
/// map.for_each(|_, v: &u64| {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

why remove this? Unless I'm missing something it clarifies the example.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added back

Comment thread ipld/hamt/src/node.rs Outdated
where
F: FnMut(&K, &V) -> anyhow::Result<()>,
S: Blockstore,
K: Clone,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Do we actually need to implement clone? I tried compiling with the trait removed from requirements here and Node and things seem to work.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You're right, Clone is no longer needed. Removed.

@github-project-automation github-project-automation Bot moved this from 🔎 Awaiting Review to ✔️ Approved by reviewer in FilOz Feb 25, 2026
@LesnyRumcajs
LesnyRumcajs merged commit 8e2f86b into filecoin-project:master Feb 26, 2026
17 checks passed
@github-project-automation github-project-automation Bot moved this from ✔️ Approved by reviewer to 🎉 Done in FilOz Feb 26, 2026
@hanabi1224
hanabi1224 deleted the hamt/for_each_cacheless branch March 6, 2026 11:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 🎉 Done

Development

Successfully merging this pull request may close these issues.

6 participants