Skip to content

feat: DatabaseCommit::commit_iter#3197

Merged
rakita merged 4 commits intobluealloy:mainfrom
0xForerunner:commit_iter
Dec 3, 2025
Merged

feat: DatabaseCommit::commit_iter#3197
rakita merged 4 commits intobluealloy:mainfrom
0xForerunner:commit_iter

Conversation

@0xForerunner
Copy link
Contributor

closes #3196

fn commit(&mut self, changes: HashMap<Address, Account>)

is overly restrictive and forces additional computation by constructing a HashMap. I suggest adding an additional overridable trait method for use cases that don't require a HashMap.

This PR provides a way around reconstructing a HashMap. Additionally I've overridden the implementation for State which should give a bit of added efficiency.

I have included a breaking change by returning an Iterator in apply_evm_state. This allows passing through an iterator rather than unnecessarily collecting into a Vec which should be more efficient. If we don't want a breaking change then I'm happy to revert just that part.

@0xForerunner 0xForerunner changed the title Commit iter feat: DatabaseCommit::commit_iter Nov 28, 2025
@codspeed-hq
Copy link

codspeed-hq bot commented Nov 28, 2025

CodSpeed Performance Report

Merging #3197 will not alter performance

Comparing 0xForerunner:commit_iter (20d4aca) with main (d013bc2)

Summary

✅ 173 untouched

/// Implementors of [`DatabaseCommit`] should override this method when possible for efficiency.
///
/// Callers should prefer using [`DatabaseCommit::commit`] when they already have a [`HashMap`].
fn commit_iter(&mut self, changes: impl IntoIterator<Item = (Address, Account)>) {
Copy link
Member

Choose a reason for hiding this comment

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

This makes a lot of sense, even for it to become the main required fn in future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I made it this way to avoid breaking changes, but we could absolutely invert the dependency between commit and commit_iter.

Copy link
Member

Choose a reason for hiding this comment

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

Database/DatabaseCommit are one of oldest traits in repo, it is good that we are not breaking it

Copy link
Member

@rakita rakita left a comment

Choose a reason for hiding this comment

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

I can't see why test would fail here

pub fn apply_evm_state<'a>(
&'a mut self,
evm_state: impl IntoIterator<Item = (Address, Account)> + 'a,
) -> impl Iterator<Item = (Address, TransitionAccount)> + 'a {
Copy link
Member

Choose a reason for hiding this comment

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

Hm is this maybe a problem. If we don't collect/iterate over returned Iterator, would the changes still be applied?

Copy link
Member

Choose a reason for hiding this comment

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

lol, it is: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=30b3aaa62884a42cf12eaf5f99262a5c

Lets return vec here, it will get optimized by compiler, and returning a iterator is a footgun.

Would additionally add #[inline] as a hint.

Copy link
Contributor Author

@0xForerunner 0xForerunner Dec 3, 2025

Choose a reason for hiding this comment

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

I don't think the collection into Vec will be optimized by the compiler, but this also isn't really a huge deal.

If we don't collect/iterate over returned Iterator, would the changes still be applied?

Ah you're right. This could be a foot gun, although I do think the caller would get a clippy lint for the unused iterator. I'll revert this though, thanks for the feedback!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted!

Comment on lines 320 to +332
impl<DB: Database> DatabaseCommit for State<DB> {
fn commit(&mut self, evm_state: HashMap<Address, Account>) {
let transitions = self.cache.apply_evm_state(evm_state);
self.apply_transition(transitions);
fn commit(&mut self, changes: HashMap<Address, Account>) {
let transitions = self.cache.apply_evm_state(changes);
if let Some(s) = self.transition_state.as_mut() {
s.add_transitions(transitions)
}
}

fn commit_iter(&mut self, changes: impl IntoIterator<Item = (Address, Account)>) {
let transitions = self.cache.apply_evm_state(changes);
if let Some(s) = self.transition_state.as_mut() {
s.add_transitions(transitions)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Since HashMap implements IntoIterator, commit can just delegate to commit_iter..I believe

fn commit(&mut self, changes: HashMap<Address, Account>) {
        self.commit_iter(changes)
    }

this removes redundancy and avoids future updates in multiple locations if if the transition logic ever changes ofc

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well either commit depends on commit_iter or vice versa haha. We can't have both I chose my way because it doesn't have breaking changes.

Copy link
Contributor

Choose a reason for hiding this comment

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

makes sense then

Copy link
Member

@rakita rakita left a comment

Choose a reason for hiding this comment

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

nice one

@rakita rakita merged commit 049da17 into bluealloy:main Dec 3, 2025
30 checks passed
@github-actions github-actions bot mentioned this pull request Dec 3, 2025
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.

[Feature] Implement DatabaseCommit::commit_iter for more versatility.

3 participants