mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-04-30 03:01:58 -04:00
Compare commits
4 Commits
push
...
adaptive-h
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aabb9c858b | ||
|
|
d123ba89ef | ||
|
|
0cb4df9b9e | ||
|
|
c405e72f6c |
@@ -208,9 +208,9 @@ impl<T> ExecutionOutcome<T> {
|
||||
}
|
||||
|
||||
/// Returns [`HashedPostState`] for this execution outcome.
|
||||
/// See [`HashedPostState::from_bundle_state`] for more info.
|
||||
/// See [`HashedPostState::from_bundle_state_adaptive`] for more info.
|
||||
pub fn hash_state_slow<KH: KeyHasher>(&self) -> HashedPostState {
|
||||
HashedPostState::from_bundle_state::<KH>(&self.bundle.state)
|
||||
HashedPostState::from_bundle_state_adaptive::<KH>(&self.bundle.state)
|
||||
}
|
||||
|
||||
/// Transform block number to the index of block.
|
||||
|
||||
@@ -148,7 +148,7 @@ impl StateProofProvider for StateProviderTest {
|
||||
|
||||
impl HashedPostStateProvider for StateProviderTest {
|
||||
fn hashed_post_state(&self, bundle_state: &revm::database::BundleState) -> HashedPostState {
|
||||
HashedPostState::from_bundle_state::<KeccakKeyHasher>(bundle_state.state())
|
||||
HashedPostState::from_bundle_state_adaptive::<KeccakKeyHasher>(bundle_state.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -359,7 +359,7 @@ async fn run_pipeline_forward_and_unwind(
|
||||
|
||||
// Convert bundle state to hashed post state and compute state root
|
||||
let hashed_state =
|
||||
HashedPostState::from_bundle_state::<KeccakKeyHasher>(output.state.state());
|
||||
HashedPostState::from_bundle_state_adaptive::<KeccakKeyHasher>(output.state.state());
|
||||
let (state_root, _trie_updates) = StateRoot::overlay_root_with_updates(
|
||||
provider.tx_ref(),
|
||||
&hashed_state.clone().into_sorted(),
|
||||
|
||||
@@ -621,7 +621,7 @@ impl<N: ProviderNodeTypes> StateProviderFactory for BlockchainProvider<N> {
|
||||
|
||||
impl<N: NodeTypesWithDB> HashedPostStateProvider for BlockchainProvider<N> {
|
||||
fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState {
|
||||
HashedPostState::from_bundle_state::<KeccakKeyHasher>(bundle_state.state())
|
||||
HashedPostState::from_bundle_state_adaptive::<KeccakKeyHasher>(bundle_state.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -719,7 +719,7 @@ impl<N: ProviderNodeTypes> PruneCheckpointReader for ProviderFactory<N> {
|
||||
|
||||
impl<N: ProviderNodeTypes> HashedPostStateProvider for ProviderFactory<N> {
|
||||
fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState {
|
||||
HashedPostState::from_bundle_state::<KeccakKeyHasher>(bundle_state.state())
|
||||
HashedPostState::from_bundle_state_adaptive::<KeccakKeyHasher>(bundle_state.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -491,7 +491,7 @@ impl<
|
||||
|
||||
impl<Provider> HashedPostStateProvider for HistoricalStateProviderRef<'_, Provider> {
|
||||
fn hashed_post_state(&self, bundle_state: &revm_database::BundleState) -> HashedPostState {
|
||||
HashedPostState::from_bundle_state::<KeccakKeyHasher>(bundle_state.state())
|
||||
HashedPostState::from_bundle_state_adaptive::<KeccakKeyHasher>(bundle_state.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ impl<Provider: DBProvider> StateProofProvider for LatestStateProviderRef<'_, Pro
|
||||
|
||||
impl<Provider: DBProvider> HashedPostStateProvider for LatestStateProviderRef<'_, Provider> {
|
||||
fn hashed_post_state(&self, bundle_state: &revm_database::BundleState) -> HashedPostState {
|
||||
HashedPostState::from_bundle_state::<KeccakKeyHasher>(bundle_state.state())
|
||||
HashedPostState::from_bundle_state_adaptive::<KeccakKeyHasher>(bundle_state.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,20 +52,7 @@ impl HashedPostState {
|
||||
) -> Self {
|
||||
state
|
||||
.into_par_iter()
|
||||
.map(|(address, account)| {
|
||||
let hashed_address = KH::hash_key(address);
|
||||
let hashed_account = account.info.as_ref().map(Into::into);
|
||||
let hashed_storage = HashedStorage::from_plain_storage(
|
||||
account.status,
|
||||
account.storage.iter().map(|(slot, value)| (slot, &value.present_value)),
|
||||
);
|
||||
|
||||
(
|
||||
hashed_address,
|
||||
hashed_account,
|
||||
(!hashed_storage.is_empty()).then_some(hashed_storage),
|
||||
)
|
||||
})
|
||||
.map(|(address, account)| Self::hash_bundle_account::<KH>(address, account))
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -78,23 +65,57 @@ impl HashedPostState {
|
||||
) -> Self {
|
||||
state
|
||||
.into_iter()
|
||||
.map(|(address, account)| {
|
||||
let hashed_address = KH::hash_key(address);
|
||||
let hashed_account = account.info.as_ref().map(Into::into);
|
||||
let hashed_storage = HashedStorage::from_plain_storage(
|
||||
account.status,
|
||||
account.storage.iter().map(|(slot, value)| (slot, &value.present_value)),
|
||||
);
|
||||
|
||||
(
|
||||
hashed_address,
|
||||
hashed_account,
|
||||
(!hashed_storage.is_empty()).then_some(hashed_storage),
|
||||
)
|
||||
})
|
||||
.map(|(address, account)| Self::hash_bundle_account::<KH>(address, account))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Initialize [`HashedPostState`] from bundle state, choosing between sequential and parallel
|
||||
/// hashing based on the number of accounts.
|
||||
///
|
||||
/// For small account counts (≤ [`Self::ADAPTIVE_THRESHOLD`]), sequential iteration avoids
|
||||
/// rayon's fixed scheduling overhead, which can exceed the hashing work itself.
|
||||
#[cfg(feature = "rayon")]
|
||||
pub fn from_bundle_state_adaptive<KH: KeyHasher>(
|
||||
state: &HashMap<Address, BundleAccount>,
|
||||
) -> Self {
|
||||
if state.len() <= Self::ADAPTIVE_THRESHOLD {
|
||||
state
|
||||
.iter()
|
||||
.map(|(address, account)| Self::hash_bundle_account::<KH>(address, account))
|
||||
.collect()
|
||||
} else {
|
||||
let entries: Vec<_> = state.iter().collect();
|
||||
Self::from_bundle_state::<KH>(entries)
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize [`HashedPostState`] from bundle state sequentially (non-rayon fallback).
|
||||
#[cfg(not(feature = "rayon"))]
|
||||
pub fn from_bundle_state_adaptive<KH: KeyHasher>(
|
||||
state: &HashMap<Address, BundleAccount>,
|
||||
) -> Self {
|
||||
Self::from_bundle_state::<KH>(state)
|
||||
}
|
||||
|
||||
/// Account count at or below which sequential hashing outperforms rayon parallel iteration.
|
||||
#[cfg(feature = "rayon")]
|
||||
pub const ADAPTIVE_THRESHOLD: usize = 32;
|
||||
|
||||
/// Hashes a single bundle account entry into the tuple expected by [`FromIterator`].
|
||||
fn hash_bundle_account<KH: KeyHasher>(
|
||||
address: &Address,
|
||||
account: &BundleAccount,
|
||||
) -> (B256, Option<Account>, Option<HashedStorage>) {
|
||||
let hashed_address = KH::hash_key(address);
|
||||
let hashed_account = account.info.as_ref().map(Into::into);
|
||||
let hashed_storage = HashedStorage::from_plain_storage(
|
||||
account.status,
|
||||
account.storage.iter().map(|(slot, value)| (slot, &value.present_value)),
|
||||
);
|
||||
|
||||
(hashed_address, hashed_account, (!hashed_storage.is_empty()).then_some(hashed_storage))
|
||||
}
|
||||
|
||||
/// Construct [`HashedPostState`] from a single [`HashedStorage`].
|
||||
pub fn from_hashed_storage(hashed_address: B256, storage: HashedStorage) -> Self {
|
||||
Self {
|
||||
|
||||
@@ -9,7 +9,7 @@ pub fn hash_post_state(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("Hash Post State");
|
||||
group.sample_size(20);
|
||||
|
||||
for size in [100, 1_000, 3_000, 5_000, 10_000] {
|
||||
for size in [10, 20, 32, 50, 100, 1_000, 3_000, 5_000, 10_000] {
|
||||
// Too slow.
|
||||
#[expect(unexpected_cfgs)]
|
||||
if cfg!(codspeed) && size > 1_000 {
|
||||
@@ -27,6 +27,13 @@ pub fn hash_post_state(c: &mut Criterion) {
|
||||
group.bench_function(BenchmarkId::new("parallel hashing", size), |b| {
|
||||
b.iter(|| HashedPostState::from_bundle_state::<KeccakKeyHasher>(&state))
|
||||
});
|
||||
|
||||
// adaptive
|
||||
let state_map: alloy_primitives::map::HashMap<Address, BundleAccount> =
|
||||
state.iter().map(|(k, v)| (*k, v.clone())).collect();
|
||||
group.bench_function(BenchmarkId::new("adaptive hashing", size), |b| {
|
||||
b.iter(|| HashedPostState::from_bundle_state_adaptive::<KeccakKeyHasher>(&state_map))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ fn run_case(case: &BlockchainTest) -> Result<(), Error> {
|
||||
|
||||
// Compute and check the post state root
|
||||
let hashed_state =
|
||||
HashedPostState::from_bundle_state::<KeccakKeyHasher>(output.state.state());
|
||||
HashedPostState::from_bundle_state_adaptive::<KeccakKeyHasher>(output.state.state());
|
||||
let (computed_state_root, _) = StateRoot::overlay_root_with_updates(
|
||||
provider.tx_ref(),
|
||||
&hashed_state.clone_into_sorted(),
|
||||
|
||||
Reference in New Issue
Block a user