Skip to content

Commit

Permalink
Merge pull request #3467 from onflow/leo/v-0.28-no-migration-optimiza…
Browse files Browse the repository at this point in the history
…tion

[State Extraction] no migration optimization
  • Loading branch information
zhangchiqing authored Oct 28, 2022
2 parents 5bb4866 + ab2af85 commit b9b941d
Showing 1 changed file with 59 additions and 48 deletions.
107 changes: 59 additions & 48 deletions ledger/complete/ledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,61 +363,66 @@ func (l *Ledger) ExportCheckpointAt(
fmt.Errorf("failed to clean up tries to reduce memory usage: %w", err)
}

// TODO enable validity check of trie
// only check validity of the trie we are interested in
// l.logger.Info().Msg("Checking validity of the trie at the given state...")
// if !t.IsAValidTrie() {
// return nil, fmt.Errorf("trie is not valid: %w", err)
// }
// l.logger.Info().Msg("Trie is valid.")

// get all payloads
payloads := t.AllPayloads()
payloadSize := len(payloads)

// migrate payloads
for i, migrate := range migrations {
l.logger.Info().Msgf("migration %d/%d is underway", i, len(migrations))

start := time.Now()
payloads, err = migrate(payloads)
elapsed := time.Since(start)

if err != nil {
return ledger.State(hash.DummyHash), fmt.Errorf("error applying migration (%d): %w", i, err)
var payloads []ledger.Payload
var newTrie *trie.MTrie

noMigration := len(migrations) == 0

if noMigration {
// when there is no migration, reuse the trie without rebuilding it
newTrie = t
// when there is no migration, we don't generate the payloads here until later running the
// postCheckpointReporters, because the ExportReporter is currently the only
// preCheckpointReporters, which doesn't use the payloads.
} else {
// get all payloads
payloads = t.AllPayloads()
payloadSize := len(payloads)

// migrate payloads
for i, migrate := range migrations {
l.logger.Info().Msgf("migration %d/%d is underway", i, len(migrations))

start := time.Now()
payloads, err = migrate(payloads)
elapsed := time.Since(start)

if err != nil {
return ledger.State(hash.DummyHash), fmt.Errorf("error applying migration (%d): %w", i, err)
}

newPayloadSize := len(payloads)

if payloadSize != newPayloadSize {
l.logger.Warn().
Int("migration_step", i).
Int("expected_size", payloadSize).
Int("outcome_size", newPayloadSize).
Msg("payload counts has changed during migration, make sure this is expected.")
}
l.logger.Info().Str("timeTaken", elapsed.String()).Msgf("migration %d is done", i)

payloadSize = newPayloadSize
}

newPayloadSize := len(payloads)
l.logger.Info().Msgf("creating paths for %v payloads", len(payloads))

if payloadSize != newPayloadSize {
l.logger.Warn().
Int("migration_step", i).
Int("expected_size", payloadSize).
Int("outcome_size", newPayloadSize).
Msg("payload counts has changed during migration, make sure this is expected.")
// get paths
paths, err := pathfinder.PathsFromPayloads(payloads, targetPathFinderVersion)
if err != nil {
return ledger.State(hash.DummyHash), fmt.Errorf("cannot export checkpoint, can't construct paths: %w", err)
}
l.logger.Info().Str("timeTaken", elapsed.String()).Msgf("migration %d is done", i)

payloadSize = newPayloadSize
}

l.logger.Info().Msgf("creating paths for %v payloads", len(payloads))

// get paths
paths, err := pathfinder.PathsFromPayloads(payloads, targetPathFinderVersion)
if err != nil {
return ledger.State(hash.DummyHash), fmt.Errorf("cannot export checkpoint, can't construct paths: %w", err)
}

l.logger.Info().Msgf("constructing a new trie with migrated payloads (count: %d)...", len(payloads))
l.logger.Info().Msgf("constructing a new trie with migrated payloads (count: %d)...", len(payloads))

emptyTrie := trie.NewEmptyMTrie()
emptyTrie := trie.NewEmptyMTrie()

// no need to prune the data since it has already been prunned through migrations
applyPruning := false
newTrie, _, err := trie.NewTrieWithUpdatedRegisters(emptyTrie, paths, payloads, applyPruning)
if err != nil {
return ledger.State(hash.DummyHash), fmt.Errorf("constructing updated trie failed: %w", err)
// no need to prune the data since it has already been prunned through migrations
applyPruning := false
newTrie, _, err = trie.NewTrieWithUpdatedRegisters(emptyTrie, paths, payloads, applyPruning)
if err != nil {
return ledger.State(hash.DummyHash), fmt.Errorf("constructing updated trie failed: %w", err)
}
}

statecommitment := ledger.State(newTrie.RootHash())
Expand Down Expand Up @@ -467,6 +472,12 @@ func (l *Ledger) ExportCheckpointAt(

l.logger.Info().Msgf("start running post-checkpoint reporters")

if noMigration {
// when there is no mgiration, we generate the payloads now before
// running the postCheckpointReporters
payloads = newTrie.AllPayloads()
}

// running post checkpoint reporters
for i, reporter := range postCheckpointReporters {
l.logger.Info().Msgf("running a post-checkpoint generation reporter: %s, (%v/%v)", reporter.Name(), i, len(postCheckpointReporters))
Expand Down

0 comments on commit b9b941d

Please sign in to comment.