Skip to content

Commit 7284b13

Browse files
authored
bench: print pure execution time in gigagas bench (#21)
- avoid copying txs in gigagas bench iterations - print pure execution time in gigagas bench
1 parent 07a65fd commit 7284b13

File tree

7 files changed

+121
-62
lines changed

7 files changed

+121
-62
lines changed

benches/gigagas.rs

Lines changed: 87 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion};
1616
use fastrace::{collector::Config, prelude::*};
1717
use fastrace_jaeger::JaegerReporter;
1818
use grevm::GrevmScheduler;
19+
use metrics::{SharedString, Unit};
20+
use metrics_util::{
21+
debugging::{DebugValue, DebuggingRecorder},
22+
CompositeKey, MetricKind,
23+
};
1924
use rand::Rng;
2025
use revm::primitives::{alloy_primitives::U160, Address, Env, SpecId, TransactTo, TxEnv, U256};
2126
use std::{collections::HashMap, sync::Arc};
@@ -25,49 +30,96 @@ const GIGA_GAS: u64 = 1_000_000_000;
2530
#[global_allocator]
2631
static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
2732

33+
fn get_metrics_counter_value(
34+
snapshot: &HashMap<CompositeKey, (Option<Unit>, Option<SharedString>, DebugValue)>,
35+
name: &'static str,
36+
) -> u64 {
37+
match snapshot
38+
.get(&CompositeKey::new(MetricKind::Counter, metrics::Key::from_static_name(name)))
39+
{
40+
Some((_, _, DebugValue::Counter(value))) => *value,
41+
_ => panic!("{:?} not found", name),
42+
}
43+
}
44+
2845
fn bench(c: &mut Criterion, name: &str, db: InMemoryDB, txs: Vec<TxEnv>) {
2946
let mut env = Env::default();
3047
env.cfg.chain_id = NamedChain::Mainnet.into();
3148
env.block.coinbase = Address::from(U160::from(common::MINER_ADDRESS));
3249
let db = Arc::new(db);
50+
let txs = Arc::new(txs);
3351

34-
let mut group = c.benchmark_group(name);
52+
let mut group = c.benchmark_group(format!("{}({} txs)", name, txs.len()));
3553
group.bench_function("Origin Sequential", |b| {
3654
b.iter(|| {
3755
common::execute_revm_sequential(
3856
black_box(db.clone()),
3957
black_box(SpecId::LATEST),
4058
black_box(env.clone()),
41-
black_box(txs.clone()),
59+
black_box(&*txs),
4260
)
4361
})
4462
});
63+
64+
let mut num_iter: usize = 0;
65+
let mut execution_time_ns: u64 = 0;
4566
group.bench_function("Grevm Parallel", |b| {
4667
b.iter(|| {
68+
num_iter += 1;
69+
let recorder = DebuggingRecorder::new();
4770
let root = Span::root(format!("{name} Grevm Parallel"), SpanContext::random());
4871
let _guard = root.set_local_parent();
49-
let executor = GrevmScheduler::new(
50-
black_box(SpecId::LATEST),
51-
black_box(env.clone()),
52-
black_box(db.clone()),
53-
black_box(txs.clone()),
54-
);
55-
executor.parallel_execute()
72+
metrics::with_local_recorder(&recorder, || {
73+
let executor = GrevmScheduler::new(
74+
black_box(SpecId::LATEST),
75+
black_box(env.clone()),
76+
black_box(db.clone()),
77+
black_box(txs.clone()),
78+
);
79+
let _ = executor.parallel_execute();
80+
81+
let snapshot = recorder.snapshotter().snapshot().into_hashmap();
82+
execution_time_ns +=
83+
get_metrics_counter_value(&snapshot, "grevm.parallel_execute_time");
84+
execution_time_ns += get_metrics_counter_value(&snapshot, "grevm.validate_time");
85+
});
5686
})
5787
});
88+
println!(
89+
"{} Grevm Parallel average execution time: {:.2} ms",
90+
name,
91+
execution_time_ns as f64 / num_iter as f64 / 1000000.0
92+
);
93+
94+
let mut num_iter: usize = 0;
95+
let mut execution_time_ns: u64 = 0;
5896
group.bench_function("Grevm Sequential", |b| {
5997
b.iter(|| {
98+
num_iter += 1;
99+
let recorder = DebuggingRecorder::new();
60100
let root = Span::root(format!("{name} Grevm Sequential"), SpanContext::random());
61101
let _guard = root.set_local_parent();
62-
let executor = GrevmScheduler::new(
63-
black_box(SpecId::LATEST),
64-
black_box(env.clone()),
65-
black_box(db.clone()),
66-
black_box(txs.clone()),
67-
);
68-
executor.force_sequential_execute()
102+
metrics::with_local_recorder(&recorder, || {
103+
let executor = GrevmScheduler::new(
104+
black_box(SpecId::LATEST),
105+
black_box(env.clone()),
106+
black_box(db.clone()),
107+
black_box(txs.clone()),
108+
);
109+
let _ = executor.force_sequential_execute();
110+
111+
let snapshot = recorder.snapshotter().snapshot().into_hashmap();
112+
execution_time_ns +=
113+
get_metrics_counter_value(&snapshot, "grevm.sequential_execute_time");
114+
});
69115
})
70116
});
117+
println!(
118+
"{} Grevm Sequential average execution time: {:.2} ms",
119+
name,
120+
execution_time_ns as f64 / num_iter as f64 / 1000000.0
121+
);
122+
71123
group.finish();
72124
}
73125

@@ -96,15 +148,19 @@ fn bench_raw_transfers(c: &mut Criterion, db_latency_us: u64) {
96148
);
97149
}
98150

99-
fn get_account_idx(num_eoa: usize, hot_start_idx: usize, hot_ratio: f64) -> usize {
151+
fn pick_account_idx(num_eoa: usize, hot_ratio: f64) -> usize {
100152
if hot_ratio <= 0.0 {
101153
// Uniform workload
102-
rand::random::<usize>() % num_eoa
103-
} else if rand::thread_rng().gen_range(0.0..1.0) < hot_ratio {
154+
return rand::random::<usize>() % num_eoa;
155+
}
156+
157+
// Let `hot_ratio` of transactions conducted by 10% of hot accounts
158+
let hot_start_idx = (num_eoa as f64 * 0.9) as usize;
159+
if rand::thread_rng().gen_range(0.0..1.0) < hot_ratio {
104160
// Access hot
105161
hot_start_idx + rand::random::<usize>() % (num_eoa - hot_start_idx)
106162
} else {
107-
rand::random::<usize>() % (num_eoa - hot_start_idx)
163+
rand::random::<usize>() % hot_start_idx
108164
}
109165
}
110166

@@ -119,20 +175,17 @@ fn bench_dependent_raw_transfers(
119175
let mut db = InMemoryDB::new(accounts, Default::default(), Default::default());
120176
db.latency_us = db_latency_us;
121177

122-
// Let 10% of the accounts be hot accounts
123-
let hot_start_idx = common::START_ADDRESS + (num_eoa as f64 * 0.9) as usize;
124-
125178
bench(
126179
c,
127180
"Dependent Raw Transfers",
128181
db,
129182
(0..block_size)
130183
.map(|_| {
131184
let from = Address::from(U160::from(
132-
common::START_ADDRESS + get_account_idx(num_eoa, hot_start_idx, hot_ratio),
185+
common::START_ADDRESS + pick_account_idx(num_eoa, hot_ratio),
133186
));
134187
let to = Address::from(U160::from(
135-
common::START_ADDRESS + get_account_idx(num_eoa, hot_start_idx, hot_ratio),
188+
common::START_ADDRESS + pick_account_idx(num_eoa, hot_ratio),
136189
));
137190
TxEnv {
138191
caller: from,
@@ -203,12 +256,9 @@ fn benchmark_dependent_erc20(
203256
let mut txs = Vec::with_capacity(block_size);
204257
let sca = sca[0];
205258

206-
// Let 10% of the accounts be hot accounts
207-
let hot_start_idx = common::START_ADDRESS + (num_eoa as f64 * 0.9) as usize;
208-
209259
for _ in 0..block_size {
210-
let from = eoa[get_account_idx(num_eoa, hot_start_idx, hot_ratio)];
211-
let to = eoa[get_account_idx(num_eoa, hot_start_idx, hot_ratio)];
260+
let from = eoa[pick_account_idx(num_eoa, hot_ratio)];
261+
let to = eoa[pick_account_idx(num_eoa, hot_ratio)];
212262
let tx = TxEnv {
213263
caller: from,
214264
transact_to: TransactTo::Call(sca),
@@ -250,19 +300,15 @@ fn bench_hybrid(c: &mut Criterion, db_latency_us: u64, num_eoa: usize, hot_ratio
250300
(GIGA_GAS as f64 * 0.2 / erc20::ESTIMATED_GAS_USED as f64).ceil() as usize;
251301
let num_uniswap = (GIGA_GAS as f64 * 0.2 / uniswap::ESTIMATED_GAS_USED as f64).ceil() as usize;
252302

253-
// Let 10% of the accounts be hot accounts
254-
let hot_start_idx = common::START_ADDRESS + (num_eoa as f64 * 0.9) as usize;
255303
let mut state = common::mock_block_accounts(common::START_ADDRESS, num_eoa);
256304
let eoa_addresses = state.keys().cloned().collect::<Vec<_>>();
257305
let mut txs = Vec::with_capacity(num_native_transfer + num_erc20_transfer + num_uniswap);
258306

259307
for _ in 0..num_native_transfer {
260-
let from = Address::from(U160::from(
261-
common::START_ADDRESS + get_account_idx(num_eoa, hot_start_idx, hot_ratio),
262-
));
263-
let to = Address::from(U160::from(
264-
common::START_ADDRESS + get_account_idx(num_eoa, hot_start_idx, hot_ratio),
265-
));
308+
let from =
309+
Address::from(U160::from(common::START_ADDRESS + pick_account_idx(num_eoa, hot_ratio)));
310+
let to =
311+
Address::from(U160::from(common::START_ADDRESS + pick_account_idx(num_eoa, hot_ratio)));
266312
let tx = TxEnv {
267313
caller: from,
268314
transact_to: TransactTo::Call(to),
@@ -280,10 +326,10 @@ fn bench_hybrid(c: &mut Criterion, db_latency_us: u64, num_eoa: usize, hot_ratio
280326
for (sca_addr, _) in erc20_contract_accounts.iter() {
281327
for _ in 0..(num_erc20_transfer / NUM_ERC20_SCA) {
282328
let from = Address::from(U160::from(
283-
common::START_ADDRESS + get_account_idx(num_eoa, hot_start_idx, hot_ratio),
329+
common::START_ADDRESS + pick_account_idx(num_eoa, hot_ratio),
284330
));
285331
let to = Address::from(U160::from(
286-
common::START_ADDRESS + get_account_idx(num_eoa, hot_start_idx, hot_ratio),
332+
common::START_ADDRESS + pick_account_idx(num_eoa, hot_ratio),
287333
));
288334
let tx = TxEnv {
289335
caller: from,
@@ -315,7 +361,7 @@ fn bench_hybrid(c: &mut Criterion, db_latency_us: u64, num_eoa: usize, hot_ratio
315361

316362
txs.push(TxEnv {
317363
caller: Address::from(U160::from(
318-
common::START_ADDRESS + get_account_idx(num_eoa, hot_start_idx, hot_ratio),
364+
common::START_ADDRESS + pick_account_idx(num_eoa, hot_ratio),
319365
)),
320366
gas_limit: uniswap::GAS_LIMIT,
321367
gas_price: U256::from(0xb2d05e07u64),

benches/mainnet.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ fn benchmark_mainnet(c: &mut Criterion) {
3232
}
3333
_ => panic!("Missing transaction data"),
3434
};
35+
let txs = Arc::new(txs);
3536

3637
let mut env = Env::default();
3738
env.cfg.chain_id = NamedChain::Mainnet.into();
@@ -45,7 +46,7 @@ fn benchmark_mainnet(c: &mut Criterion) {
4546
black_box(db.clone()),
4647
black_box(spec_id),
4748
black_box(env.clone()),
48-
black_box(txs.clone()),
49+
black_box(&*txs),
4950
)
5051
})
5152
});

src/scheduler.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,16 @@ struct ExecuteMetrics {
5959
parse_hints_time: metrics::Counter,
6060
/// Time taken to partition transactions(in nanoseconds).
6161
partition_tx_time: metrics::Counter,
62-
/// Time taken to validate transactions(in nanoseconds).
62+
/// Time taken to execute transactions in parallel(in nanoseconds).
6363
parallel_execute_time: metrics::Counter,
64-
/// Time taken to execute
64+
/// Time taken to validate transactions(in nanoseconds).
6565
validate_time: metrics::Counter,
6666
/// Time taken to merge write set.
6767
merge_write_set_time: metrics::Counter,
6868
/// Time taken to commit transition
6969
commit_transition_time: metrics::Counter,
70+
/// Time taken to execute transactions in sequential(in nanoseconds).
71+
sequential_execute_time: metrics::Counter,
7072
/// Time taken to build output(in nanoseconds).
7173
build_output_time: metrics::Counter,
7274
}
@@ -93,6 +95,7 @@ impl Default for ExecuteMetrics {
9395
validate_time: counter!("grevm.validate_time"),
9496
merge_write_set_time: counter!("grevm.merge_write_set_time"),
9597
commit_transition_time: counter!("grevm.commit_transition_time"),
98+
sequential_execute_time: counter!("grevm.sequential_execute_time"),
9699
build_output_time: counter!("grevm.build_output_time"),
97100
}
98101
}
@@ -226,7 +229,7 @@ where
226229
>(boxed)
227230
};
228231
let db: DatabaseWrapper<DB::Error> = DatabaseWrapper(db);
229-
GrevmScheduler::new(spec_id, env, db, txs)
232+
GrevmScheduler::new(spec_id, env, db, Arc::new(txs))
230233
}
231234

232235
impl<DB> GrevmScheduler<DB>
@@ -235,7 +238,7 @@ where
235238
DB::Error: Send + Sync,
236239
{
237240
/// Creates a new GrevmScheduler instance.
238-
pub fn new(spec_id: SpecId, env: Env, db: DB, txs: Vec<TxEnv>) -> Self {
241+
pub fn new(spec_id: SpecId, env: Env, db: DB, txs: Arc<Vec<TxEnv>>) -> Self {
239242
let coinbase = env.block.coinbase;
240243
let num_partitions = *CPU_CORES * 2 + 1; // 2 * cpu + 1 for initial partition number
241244
let num_txs = txs.len();
@@ -244,7 +247,7 @@ where
244247
spec_id,
245248
env,
246249
coinbase,
247-
txs: Arc::new(txs),
250+
txs,
248251
database: Arc::new(SchedulerDB::new(db)),
249252
tx_dependencies: TxDependency::new(num_txs),
250253
tx_states: Arc::new(vec![TxState::new(); num_txs]),
@@ -561,6 +564,7 @@ where
561564
/// Fall back to sequential execution for the remaining transactions.
562565
#[fastrace::trace]
563566
fn execute_remaining_sequential(&mut self) -> Result<(), GrevmError<DB::Error>> {
567+
let start = Instant::now();
564568
self.metrics.sequential_execute_calls.increment(1);
565569
self.metrics.sequential_tx_cnt.increment((self.txs.len() - self.num_finality_txs) as u64);
566570
// MUST drop the `PartitionExecutor::scheduler_db` before get mut
@@ -585,6 +589,7 @@ where
585589
Err(err) => return Err(GrevmError::EvmError(err)),
586590
}
587591
}
592+
self.metrics.sequential_execute_time.increment(start.elapsed().as_nanos() as u64);
588593
Ok(())
589594
}
590595

tests/common/execute.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use alloy_rpc_types::Block;
33
use metrics_util::debugging::{DebugValue, DebuggingRecorder};
44

55
use alloy_chains::NamedChain;
6-
use grevm::{ExecuteOutput, GrevmError, GrevmScheduler};
6+
use grevm::{ExecuteOutput, GrevmScheduler};
77
use revm::{
88
db::{
99
states::{bundle_state::BundleRetention, StorageSlot},
@@ -113,17 +113,17 @@ pub(crate) fn compare_evm_execute<DB>(
113113
env.cfg.chain_id = NamedChain::Mainnet.into();
114114
env.block.coinbase = Address::from(U160::from(MINER_ADDRESS));
115115
let db = Arc::new(db);
116+
let txs = Arc::new(txs);
116117
let start = Instant::now();
117118
let sequential = GrevmScheduler::new(SpecId::LATEST, env.clone(), db.clone(), txs.clone());
118119
let sequential_result = sequential.force_sequential_execute();
119120
println!("Grevm sequential execute time: {}ms", start.elapsed().as_millis());
120121

121-
let mut parallel_result = Err(GrevmError::UnreachableError(String::from("Init")));
122-
metrics::with_local_recorder(&recorder, || {
122+
let parallel_result = metrics::with_local_recorder(&recorder, || {
123123
let start = Instant::now();
124124
let parallel = GrevmScheduler::new(SpecId::LATEST, env.clone(), db.clone(), txs.clone());
125125
// set determined partitions
126-
parallel_result = parallel.force_parallel_execute(with_hints, Some(23));
126+
let parallel_result = parallel.force_parallel_execute(with_hints, Some(23));
127127
println!("Grevm parallel execute time: {}ms", start.elapsed().as_millis());
128128

129129
let snapshot = recorder.snapshotter().snapshot();
@@ -133,10 +133,11 @@ pub(crate) fn compare_evm_execute<DB>(
133133
assert_eq!(*metric, value);
134134
}
135135
}
136+
parallel_result
136137
});
137138

138139
let start = Instant::now();
139-
let reth_result = execute_revm_sequential(db.clone(), SpecId::LATEST, env.clone(), txs.clone());
140+
let reth_result = execute_revm_sequential(db.clone(), SpecId::LATEST, env.clone(), &*txs);
140141
println!("Origin sequential execute time: {}ms", start.elapsed().as_millis());
141142

142143
let mut max_gas_spent = 0;
@@ -176,7 +177,7 @@ pub(crate) fn execute_revm_sequential<DB>(
176177
db: DB,
177178
spec_id: SpecId,
178179
env: Env,
179-
txs: Vec<TxEnv>,
180+
txs: &[TxEnv],
180181
) -> Result<ExecuteOutput, EVMError<DB::Error>>
181182
where
182183
DB: DatabaseRef,
@@ -192,7 +193,7 @@ where
192193

193194
let mut results = Vec::with_capacity(txs.len());
194195
for tx in txs {
195-
*evm.tx_mut() = tx;
196+
*evm.tx_mut() = tx.clone();
196197
let result_and_state = evm.transact()?;
197198
evm.db_mut().commit(result_and_state.state);
198199
results.push(result_and_state.result);

0 commit comments

Comments
 (0)