Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core/state: parallelise parts of state commit #29681

Merged
merged 4 commits into from
May 2, 2024

Conversation

karalabe
Copy link
Member

@karalabe karalabe commented Apr 29, 2024

This PR attempts to run bits and pieces of statedb.Commit concurrently to one another. The observation is that even though the code is very light, concurrency does seem to make a difference. Will post some benchmark results. Edit:

Screenshot 2024-04-29 at 20 39 43

Also, I think it's possible to make the account update run concurrently with the storage updates, which might shave even more off. Will need to run that as a benchmark too. Edit:

Screenshot 2024-04-30 at 09 07 31

internal/syncx/workerpool.go Outdated Show resolved Hide resolved
@karalabe karalabe changed the title core/state, internal/workerpool: parallelize parts of state commit core/state: parallelise parts of state commit Apr 30, 2024
@karalabe karalabe added this to the 1.14.1 milestone May 2, 2024
@karalabe karalabe merged commit 682ee82 into ethereum:master May 2, 2024
3 checks passed
// that the account was destructed and then resurrected in the same block.
// In this case, the node set is shared by both accounts.
lock.Lock()
defer lock.Unlock()
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a quick note, this locking scheme here will definitely affect performance. You're spawning concurrent work but it'll all have to synchronize after. It would be better to pre-allocate a slice of suitable size to track the output sets (or even have it as a field in StateObject), then perform the merge operation and counter updates after all commits are done.

Copy link
Member Author

Choose a reason for hiding this comment

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

If I were to wait until all results are in and then merge, then the merge wound't proceed concurrnetly with the disk reads. IMO that would be worse.

I could make a channel and stream the results out and have an outer goroutine listen and merge one by one, but that would just end up being the same as locking and allowing access one by one via the mutex.

Don't really see why it would be different.

Copy link
Contributor

Choose a reason for hiding this comment

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

The channel way would also work, and the channel could even be buffered. Writes on buffered channels are fast even under contention AFAIK, so could be an idea.

jorgemmsilva pushed a commit to iotaledger/go-ethereum that referenced this pull request Jun 17, 2024
* core/state, internal/workerpool: parallelize parts of state commit

* core, internal: move workerpool into syncx

* core/state: use errgroups, commit accounts concurrently

* core: resurrect detailed commit timers to almost-accuracy
stwiname pushed a commit to subquery/data-node-go-ethereum that referenced this pull request Sep 9, 2024
* core/state, internal/workerpool: parallelize parts of state commit

* core, internal: move workerpool into syncx

* core/state: use errgroups, commit accounts concurrently

* core: resurrect detailed commit timers to almost-accuracy
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.

5 participants