-
Notifications
You must be signed in to change notification settings - Fork 179
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
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
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
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
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.
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.
88f51cd
to
cacba0d
Compare
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 updating! I focused on non-test code and left some comments. One suggestion would prevent problems and the other suggestions are minor.
cmd/util/ledger/util/util.go
Outdated
} | ||
|
||
func (p *PayloadsReadonlyLedger) GetValue(owner, key []byte) (value []byte, err error) { | ||
v, err := p.Snapshot.Get(flow.NewRegisterID(string(owner), string(key))) |
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.
Do we need to convert owner
to Address
here?
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))) |
cmd/util/ledger/util/util.go
Outdated
} | ||
|
||
func (p *PayloadsReadonlyLedger) ValueExists(owner, key []byte) (exists bool, err error) { | ||
_, ok := p.Snapshot.Payloads[flow.NewRegisterID(string(owner), string(key))] |
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.
Do we need to convert owner
to Address
here?
_, ok := p.Snapshot.Payloads[flow.NewRegisterID(string(owner), string(key))] | |
_, ok := p.Snapshot.Payloads[flow.NewRegisterID(string(flow.BytesToAddress(owner).Bytes()), string(key))] |
log.Info(). | ||
Int("account_count", accountGroups.Len()). | ||
Int("payload_count", len(allPayloads)). | ||
Msgf("finished migrating Payloads") |
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.
do we want to log the total duration here?
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.
The outer framework already does that.
continue | ||
} | ||
|
||
if _, ok := knownProblematicAccounts[job.Address]; ok { |
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.
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.
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.
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, |
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.
Just to check is it guaranteed that there is no duplication in the payloads?
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.
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 |
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.
Maybe return a bool to indicate there is no migration for this account. Is it useful to report how many accounts are migrated?
return payloads, nil | |
return payloads, false, nil |
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.
I feel like the individual migration should do this reporting if needed, since a lot of the time all accounts need migration.
logAccount(1) | ||
} | ||
if contextDone { | ||
break |
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.
Is it possible to reach this?
If contextDone
is true, it must have called break
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.
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()) |
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 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.
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.
That is what the groups1
are.
groups2
are with concurrency groups1
are without.
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.
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.
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.
added.
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.
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{} |
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.
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.
groups3 := map[common.Address][]*ledger.Payload{} | |
groups3 := map[common.Address]map[ledger.Path]*ledger.Payload |
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.
I added a require.ElementsMatch
to check for this
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: