refactor: drop redundant Arc<Bytecode> indirection#144
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
LGTM. The reasoning is sound — The replacement of One coordination note already called out in the description: the |
The Arc<Bytecode> removal rewrote the `.cloned()` in `code_by_hash_ref`, but revm reads contract code inline via `basic_ref`'s `AccountInfo.code`, so the by-hash path was never exercised and codecov flagged it as the one uncovered line in the patch. Add a focused unit test covering the empty-code short-circuit, present-hash hit, and absent-hash error. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
LGTM. The premise is correct: Changes look correct throughout: the pointer check in The breaking change to |
|
之前 review 这个 PR 时发现 bytecode code 内部已经优化 clone(还的是 Fable 5):https://github.com/megaeth-labs/mega-reth/pull/1867 |
|
Clean, well-justified refactor. The premise is correct: The change is mechanical across all 14 files, tests pass, and the new One nit on the new test's assertion: // pointer equality implies the bytes match, so it also confirms the right code came back.
assert_eq!(got.bytes_slice().as_ptr(), code.bytes_slice().as_ptr());The comment mixes two concerns: shared allocation (what the pointer check proves) and identity (which bytecode came back). Pointer equality is sufficient evidence for both here, but if someone inserts a second entry into the map with the same bytes at a different hash, the pointer check could theoretically pass while returning the wrong entry. Separating the assertions would make the intent clearer: one LGTM. |
|
LGTM. The premise is correct — |
Summary
Bytecode(revm::state::Bytecode, fromrevm-bytecode6.2.2) is already internally reference-counted, so wrapping it inArc<Bytecode>was a redundant second layer of indirection. This replacesArc<Bytecode>with plainBytecodeeverywhere it was stored or exchanged (contract cache,ContractStoretrait, RPC fetch, witness DB, trace data), dropping one heap allocation and one pointer hop per contract while keeping clones cheap.Why
Bytecodeis an enum whose every field is eitherCopyorArc/Bytes-backed:So
Bytecode::clone()is already an O(1) refcount bump that shares the same allocation — not a deep copy. The outerArconly saved copying ~7 words of enum metadata, at the cost of an extra heap allocation per contract and an indirection on every access. It also gave zero benefit on the hottest path:revm::DatabaseRefrequires an ownedBytecode, soWitnessDatabasealready did(**arc).clone()at the read boundary, cloning the innerBytecoderegardless. The previous doc comments justified theArcas avoiding a "deep-clone on every cache hit," but that premise was false.What changed
Type substitution
Arc<Bytecode>->Bytecode(plus removal of theArc::new(..)/(**arc).clone()/.as_ref()adapters and rewritten rationale comments), across: core contract instateless-core(ContractLookup+ContractStoretrait indb.rs,WitnessDatabase.contractsinevm_database.rs,validate_blockinexecutor.rs); cache / persistence instateless-db(ContractCacheweighter/map/get/insert incache.rs, redb read/write inhelpers.rs); RPC / fixtures (RpcClient::get_codes*inrpc_client.rs,TestFixturesinfixtures.rs); and the binaries (validator_db.rs,server_db.rs,data_provider.rs,tracing_executor.rs, bothchain_sync.rs). The cache test that assertedArc::ptr_eqnow compares the underlying buffer pointer, demonstrating the shared-allocation property directly. Net diff: 14 files, +100 / -122.Performance
A wash-to-slight-improvement with no deep copies introduced anywhere. Cache hit goes from an
Arcclone (1 atomic inc) to aBytecodeclone (2 atomic incs), offset by removing theArc::newheap box and a pointer hop; EVMcode_by_hash_ref/basic_refdo identical work minus the(**arc)deref; andBlockDataclone (trace single-flight) still shares every underlying buffer.Breaking change
This changes the public
ContractStoretrait (ContractLookupandadd_contracts) fromArc<Bytecode>toBytecode. The out-of-tree mega-rethFullNodeimplementsChainStore: ContractStoreand needs the same one-line type change in its impl — a coordination point for the EL compat matrix.Testing
cargo check --workspace --all-targets— cleancargo clippy --workspace --all-targets --all-features— no warningscargo fmt --all --check— cleancargo test --workspace— 209 passed, 0 failed