Conversation
…s, avoid decode, make resumable, tune batch size
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## maksym/statehistory-migration #4070 +/- ##
==============================================================
Coverage 79.21% 79.21%
==============================================================
Files 472 471 -1
Lines 36089 36130 +41
==============================================================
+ Hits 28587 28620 +33
- Misses 7493 7501 +8
Partials 9 9 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
NazariiDenha
left a comment
There was a problem hiding this comment.
One more thing is resumability in case of error
For example, if we encounter error during nonce phase - the intermediate state will be nil and migrator will start again from first phase class-hash. deprecated bucket will be wiped at that time and nothing happens for that phase, but still it doesn't store actual state.
Probably, there is the same problem in outer state migration with headstate, history and trie phases
| deprecatedPrefix := db.DeprecatedContractClassHashHistoryKey(addrFelt) | ||
| contract, err := state.GetContract(i.Database, addrFelt) | ||
| contractKey := fillAddressKey(scratch.contractKey[:], db.Contract, &addr) | ||
| headClassHash, deployHeight, err := readHeadClassHash(i.Database, contractKey) |
There was a problem hiding this comment.
we already read head contract data when producing input in addressSeq and could pass some kind of headRecord instead of addr from addressSeq here and in nonce_ingestor. This could eliminate 2 random point reads per contract which gave significant improve on headstate migration, but maybe here it will not give that much
|
My results
Strange that I didn't get any improve on |

User description
Reworks the contract history migration for speed and resumability: the per-contract DeleteRange becomes one bucket wipe per phase (interleaved tombstones were quadratic in pebble, −40% on mainnet), rows move as raw bytes through reusable per-worker key buffers instead of a decode/encode round-trip, and the batch target drops to 32 MB to stay under pebble's large-batch threshold (−25% memtable stall). On cancellation the source records the first address it never handed out and Before resumes there, skipping completed phases. Output is verified byte-identical to the previous implementation on a seed covering every branch of all three phases.
Mainnet migration (377 GB snapshot, same machine):
Attribution from isolating each change: the bucket wipe is ≈ −1050 s, the 32 MB batch ≈ −73 s; the allocation work removes GC pressure but did not move wall-clock, which was memtable-stall bound.
Micro-benchmark (per contract; storage seeds 1024 entries, nonce 16, class-hash 17):
Methodology. Micro:
go test -benchagainst pebble in a temp dir, one seeded contract, 500 iterations × 8 runs, parent commit vs HEAD run sequentially and compared with benchstat. Mainnet: the full migration on a snapshot restored to the same pristine state before every run, phase times from the migration log, stall fromdb_write_stall{type="memtable"}, each configuration run twice.PR Type
Enhancement, Tests
Description
Optimize migration with zero-allocation byte buffers.
historyScratchbuffers.UncopiedKeyto DB iterators.Enable migration resumability across phases.
Reduce Pebble batch target size to 32MB.
Wipe deprecated buckets per-phase instead of per-contract.
File Walkthrough
8 files
Add `UncopiedKey` method to Iterator interfaceImplement `UncopiedKey` in memory iteratorImplement `UncopiedKey` in pebble iteratorImplement `UncopiedKey` in pebblev2 iteratorImplement `UncopiedKey` in remote iteratorIntroduce `historyScratch` buffers and byte manipulatorsImplement resumability and per-phase bucket wipingAdd timing logs for overall migration and phases1 files
Reduce batch target sizes to avoid memtable stalls4 files
Remove context awareness from `BaseIngestor` flushUpdate `newIngestor` signature to remove contextUpdate `newIngestor` call to reflect signature changeRemove deprecated parse functions in favor of raw bytes3 files
Optimize class-hash migration using raw byte buffersOptimize nonce migration using raw byte buffersOptimize storage migration using raw byte buffers3 files
Add tests for history key operations and record readingUpdate and expand history migrator tests for resumabilityAdd tests to validate migration interruption and resume logic