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

Migrate-by-account changes #5128

Merged
merged 9 commits into from
Jan 8, 2024
Merged

Conversation

janezpodhostnik
Copy link
Contributor

Not all of this is in use yet, but its extracted from a larger PR #4633 so that it can be reviewed separately.

The most notable changes are:

  • changes to the Account based migrator so that once the account grouping is done multiple migrators can be used to migrate one account
  • grouping is done via sorting which speeds up the grouping
  • introduced a partial runtime interface implementation so it can be used in the migrations

@codecov-commenter
Copy link

codecov-commenter commented Dec 11, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (38484eb) 56.49% compared to head (1833916) 63.57%.
Report is 85 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5128      +/-   ##
==========================================
+ Coverage   56.49%   63.57%   +7.08%     
==========================================
  Files         980       13     -967     
  Lines       93192     1650   -91542     
==========================================
- Hits        52649     1049   -51600     
+ Misses      36640      518   -36122     
+ Partials     3903       83    -3820     
Flag Coverage Δ
unittests 63.57% <ø> (+7.08%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@janezpodhostnik janezpodhostnik changed the title Add Migration infrastructure Migrate-by-account changes Dec 11, 2023
Copy link
Member

@fxamacker fxamacker left a comment

Choose a reason for hiding this comment

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

Great work! 🙌 Thanks for using parallel sort to group accounts!

I focused on non-test code and left some comments. Some tweaks can reduce memory usage by gigabytes and improve speed.

cmd/util/ledger/util/migration_runtime_interface.go Outdated Show resolved Hide resolved
cmd/util/ledger/util/util.go Outdated Show resolved Hide resolved
cmd/util/ledger/util/util.go Outdated Show resolved Hide resolved
cmd/util/ledger/util/util.go Outdated Show resolved Hide resolved
cmd/util/ledger/util/util.go Outdated Show resolved Hide resolved
cmd/util/ledger/migrations/storage_used_migration.go Outdated Show resolved Hide resolved
cmd/util/ledger/migrations/account_based_migration.go Outdated Show resolved Hide resolved
cmd/util/ledger/migrations/account_based_migration.go Outdated Show resolved Hide resolved
cmd/util/ledger/migrations/account_based_migration.go Outdated Show resolved Hide resolved
@janezpodhostnik janezpodhostnik force-pushed the janez/migration-infrastructure branch from 88f51cd to cacba0d Compare December 12, 2023 16:22
Copy link
Member

@fxamacker fxamacker left a comment

Choose a reason for hiding this comment

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

Thanks for updating! I focused on non-test code and left some comments. One suggestion would prevent problems and the other suggestions are minor.

}

func (p *PayloadsReadonlyLedger) GetValue(owner, key []byte) (value []byte, err error) {
v, err := p.Snapshot.Get(flow.NewRegisterID(string(owner), string(key)))
Copy link
Member

Choose a reason for hiding this comment

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

Do we need to convert owner to Address here?

Suggested change
v, err := p.Snapshot.Get(flow.NewRegisterID(string(owner), string(key)))
v, err := p.Snapshot.Get(flow.NewRegisterID(string(flow.BytesToAddress(owner).Bytes()), string(key)))

}

func (p *PayloadsReadonlyLedger) ValueExists(owner, key []byte) (exists bool, err error) {
_, ok := p.Snapshot.Payloads[flow.NewRegisterID(string(owner), string(key))]
Copy link
Member

Choose a reason for hiding this comment

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

Do we need to convert owner to Address here?

Suggested change
_, ok := p.Snapshot.Payloads[flow.NewRegisterID(string(owner), string(key))]
_, ok := p.Snapshot.Payloads[flow.NewRegisterID(string(flow.BytesToAddress(owner).Bytes()), string(key))]

cmd/util/ledger/util/payload_grouping.go Outdated Show resolved Hide resolved
cmd/util/ledger/util/payload_grouping.go Outdated Show resolved Hide resolved
cmd/util/ledger/util/payload_grouping.go Outdated Show resolved Hide resolved
cmd/util/ledger/migrations/storage_used_migration.go Outdated Show resolved Hide resolved
cmd/util/ledger/migrations/account_based_migration.go Outdated Show resolved Hide resolved
cmd/util/ledger/migrations/account_based_migration.go Outdated Show resolved Hide resolved
cmd/util/ledger/migrations/account_based_migration.go Outdated Show resolved Hide resolved
log.Info().
Int("account_count", accountGroups.Len()).
Int("payload_count", len(allPayloads)).
Msgf("finished migrating Payloads")
Copy link
Member

Choose a reason for hiding this comment

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

do we want to log the total duration here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The outer framework already does that.

cmd/util/ledger/migrations/account_based_migration.go Outdated Show resolved Hide resolved
cmd/util/ledger/migrations/account_based_migration.go Outdated Show resolved Hide resolved
continue
}

if _, ok := knownProblematicAccounts[job.Address]; ok {
Copy link
Member

Choose a reason for hiding this comment

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

Do we need some statistic for how many problematic account we actually see?

Such as a log shows at the end saying, "seen 90 problemetic accounts among the 100 knownProblemeticAccounts, total unmigrated payloads: 3020".

This could allow us to capture some mistake, for instance, if it says seen 0 problemetic accounts among the 0 knownProblemetic Accounts, ..., it means we probably specified a wrong knownProblemetic accounts.

This might allow us to monitor the change of these accounts.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We should always see all of them. Not sure if this would help. But I will add a log on the amount of registers.

func (m *AccountUsageMigrator) MigrateAccount(
_ context.Context,
address common.Address,
payloads []*ledger.Payload,
Copy link
Member

Choose a reason for hiding this comment

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

Just to check is it guaranteed that there is no duplication in the payloads?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

that is up to the caller, but they should be unique.

same := m.compareUsage(isOldVersionOfStatusRegister, status, actualSize)
if same {
// there is no problem with the usage, return
return payloads, nil
Copy link
Member

Choose a reason for hiding this comment

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

Maybe return a bool to indicate there is no migration for this account. Is it useful to report how many accounts are migrated?

Suggested change
return payloads, nil
return payloads, false, nil

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I feel like the individual migration should do this reporting if needed, since a lot of the time all accounts need migration.

cmd/util/ledger/migrations/storage_used_migration.go Outdated Show resolved Hide resolved
logAccount(1)
}
if contextDone {
break
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible to reach this?

If contextDone is true, it must have called break

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the select break only breaks out of the select, not out of the for loop.

copy(tmp2, payloads)

groups1 := util.GroupPayloadsByAccount(log, tmp1, 0)
groups2 := util.GroupPayloadsByAccount(log, tmp2, runtime.NumCPU())
Copy link
Member

Choose a reason for hiding this comment

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

This test case compare the result with itself, it validates the concurrency behavior, but didn't validate the correctness of the result.

In order to validate the correctness of the result, I think we should also compare with a result generated by using a map without any concurrency.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is what the groups1 are.
groups2 are with concurrency groups1 are without.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, group2 tests the validation.

Both group1 and group2 are from the same implementation which uses sort. I'm suggesting to compare with an implementation without sort, such as a simple map.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added.

Copy link
Member

@zhangchiqing zhangchiqing left a comment

Choose a reason for hiding this comment

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

Looks good, just one more comment for adding a check in test case

groups1 := util.GroupPayloadsByAccount(log, tmp1, 0)
groups2 := util.GroupPayloadsByAccount(log, tmp2, runtime.NumCPU())

groups3 := map[common.Address][]*ledger.Payload{}
Copy link
Member

Choose a reason for hiding this comment

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

For the payloads from the same address, we only compared the length, it's better to check the payloads in the same group are the same. We could do that by turning the payload group from a slice to a map, and check each of the payload in the same group exists in the map.

Suggested change
groups3 := map[common.Address][]*ledger.Payload{}
groups3 := map[common.Address]map[ledger.Path]*ledger.Payload

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a require.ElementsMatch to check for this

@janezpodhostnik janezpodhostnik added this pull request to the merge queue Jan 8, 2024
@janezpodhostnik janezpodhostnik removed this pull request from the merge queue due to a manual request Jan 8, 2024
@janezpodhostnik janezpodhostnik added this pull request to the merge queue Jan 8, 2024
Merged via the queue into master with commit f413638 Jan 8, 2024
52 checks passed
@janezpodhostnik janezpodhostnik deleted the janez/migration-infrastructure branch January 8, 2024 20:40
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.

4 participants