-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
perf: Faster state export #14332
perf: Faster state export #14332
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm!
Co-authored-by: Julien Robert <julien@rbrt.fr>
Co-authored-by: Julien Robert <julien@rbrt.fr>
Co-authored-by: Julien Robert <julien@rbrt.fr>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Thanks :)
} | ||
|
||
// verify modules exists in app, so that we don't panic in the middle of an export | ||
if err := m.checkModulesExists(modulesToExport); err != nil { | ||
panic(err) | ||
} | ||
|
||
for _, moduleName := range modulesToExport { | ||
channels := make([]chan json.RawMessage, len(modulesToExport)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One note here: this will create as many goroutines as modules. This may cause CPU contention. Limiting concurrent exports to GOMAXPROCS may improve perf slightly. This is a great PR tho and a huge improvement. Should be able to do something similar for migrations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point. but unless I'm mistaken, or things changed, Go is built to execute and handle hundreds of thousands of goroutines, whereas a typical app will have a dozen or so modules at most.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alex is correct here, go 1.18+ can handle ~500k routines per 1GB of memory. So we shouldn't have any issues here. I will mess with this more in the future to see if I can squeeze out more runtime performance.
I will also take a look at doing it for migrations too, thanks for the tip
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not all modules may implement HasGenesis
. The setup can take this into account (and use append later)
channels := make([]chan json.RawMessage, len(modulesToExport)) | |
channels := make([]chan json.RawMessage, 0, len(modulesToExport)) |
We need to check that data race in e2e tests before merging. |
Note to self: add a changelog in the backported PR. |
(cherry picked from commit de6ef1e)
} | ||
} | ||
|
||
for i, moduleName := range modulesWithGenesis { | ||
genesisData[moduleName] = <-channels[i] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are iterating over modulesWithGenesis
now which may be a subset of modulesToExport
. The i
value therefore is not the same.
For example if we have [foo
, bar
] as modules in modulesToExport
with foo
not implementing HasGenesis
then modulesWithGenesis
has only the bar
element and you would still wait for channel[0]
to return.
Some tests on this feature would be very useful
channels[i] = make(chan json.RawMessage) | ||
modulesWithGenesis = append(modulesWithGenesis, moduleName) | ||
|
||
go func(module HasGenesis, ch chan json.RawMessage) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This introduces a race condition on github.com/cosmos/cosmos-sdk/store/types.(*infiniteGasMeter).ConsumeGas()
. CI on wasmd found this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for identifying this, agree we need better tests. @Reecepbcups can you help here?
//go:build e2e | ||
// +build e2e | ||
//go:build !race | ||
// +build !race |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why deactivate?
modulesWithGenesis = append(modulesWithGenesis, moduleName) | ||
|
||
go func(module HasGenesis, ch chan json.RawMessage) { | ||
ch <- module.ExportGenesis(ctx, cdc) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To fix the gas meter race, you could set a new one per Go-routine, like ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
.
This reverts commit de6ef1e.
Description
This PR uses better logic to export the genesis state export. This has a real world performance increase of ~43% for a given export (CPU:
AMD Ryzen 5 3600 6-Core
& Disk:SAMSUNG MZVL2512HCJQ-00B00
)Author Checklist
All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.
I have...
!
to the type prefix if API or client breaking changeCHANGELOG.md
Reviewers Checklist
All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.
I have...
!
in the type prefix if API or client breaking change