diff --git a/.github/workflows/pr_perf_rlp.yaml b/.github/workflows/pr_perf_rlp.yaml
new file mode 100644
index 00000000000..e366e428655
--- /dev/null
+++ b/.github/workflows/pr_perf_rlp.yaml
@@ -0,0 +1,70 @@
+name: Benchmark RLP
+
+on:
+ pull_request:
+ branches: ["**"]
+ paths:
+ - "crates/common/rlp/**"
+ - ".github/workflows/pr_perf_rlp.yaml"
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ actions: write
+ issues: write
+ pull-requests: write
+
+jobs:
+ benchmark:
+ name: Benchmark RLP
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout sources
+ uses: actions/checkout@v4
+ with:
+ ref: 'main'
+ - name: Setup Rust Environment
+ uses: ./.github/actions/setup-rust
+ with:
+ components: rustfmt, clippy
+
+ - name: Install critcmp
+ run: cargo install critcmp
+
+ - name: Run bench main
+ continue-on-error: true
+ run: make bench-rlp
+ - name: Change to PR
+ env:
+ HEAD_REF: ${{ github.head_ref }}
+ run: |
+ git fetch origin "$HEAD_REF"
+ git checkout "$HEAD_REF"
+ - name: Run bench PR
+ run: make bench-rlp
+
+ - name: Save comparison
+ run: |
+ {
+ printf '## RLP Bench Results\n\n\nBench output
\n\n```\n'
+ critcmp --list
+ printf '\n```\n\n \n'
+ } > result.md
+
+ - name: Find comment
+ continue-on-error: true
+ uses: peter-evans/find-comment@v3
+ id: fc
+ with:
+ issue-number: ${{ github.event.pull_request.number }}
+ comment-author: "github-actions[bot]"
+ body-includes: "RLP Bench Results"
+
+ - name: Create or update comment
+ uses: peter-evans/create-or-update-comment@v4
+ with:
+ comment-id: ${{ steps.fc.outputs.comment-id }}
+ token: ${{ secrets.GITHUB_TOKEN }}
+ issue-number: ${{ github.event.pull_request.number }}
+ body-path: result.md
+ edit-mode: replace
diff --git a/Cargo.lock b/Cargo.lock
index 26d7ceaebd1..f639bc6a629 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -158,6 +158,15 @@ dependencies = [
"url",
]
+[[package]]
+name = "alloca"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5a7d05ea6aea7e9e64d25b9156ba2fee3fdd659e34e41063cd2fc7cd020d7f4"
+dependencies = [
+ "cc",
+]
+
[[package]]
name = "allocator-api2"
version = "0.2.21"
@@ -2094,7 +2103,7 @@ dependencies = [
"cast",
"ciborium",
"clap",
- "criterion-plot",
+ "criterion-plot 0.5.0",
"futures",
"is-terminal",
"itertools 0.10.5",
@@ -2112,6 +2121,32 @@ dependencies = [
"walkdir",
]
+[[package]]
+name = "criterion"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0dfe5e9e71bdcf4e4954f7d14da74d1cdb92a3a07686452d1509652684b1aab"
+dependencies = [
+ "alloca",
+ "anes",
+ "cast",
+ "ciborium",
+ "clap",
+ "criterion-plot 0.8.0",
+ "csv",
+ "itertools 0.13.0",
+ "num-traits",
+ "oorandom",
+ "page_size",
+ "plotters",
+ "rayon",
+ "regex",
+ "serde",
+ "serde_json",
+ "tinytemplate",
+ "walkdir",
+]
+
[[package]]
name = "criterion-plot"
version = "0.5.0"
@@ -2122,6 +2157,16 @@ dependencies = [
"itertools 0.10.5",
]
+[[package]]
+name = "criterion-plot"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5de36c2bee19fba779808f92bf5d9b0fa5a40095c277aba10c458a12b35d21d6"
+dependencies = [
+ "cast",
+ "itertools 0.13.0",
+]
+
[[package]]
name = "critical-section"
version = "1.2.0"
@@ -2328,6 +2373,27 @@ dependencies = [
"typenum",
]
+[[package]]
+name = "csv"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938"
+dependencies = [
+ "csv-core",
+ "itoa",
+ "ryu",
+ "serde_core",
+]
+
+[[package]]
+name = "csv-core"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "ctor"
version = "0.5.0"
@@ -3608,7 +3674,7 @@ name = "ethrex-benches"
version = "7.0.0"
dependencies = [
"bytes",
- "criterion",
+ "criterion 0.5.1",
"ethrex",
"ethrex-blockchain",
"ethrex-common",
@@ -3650,6 +3716,7 @@ dependencies = [
"crc32fast",
"ethereum-types 0.15.1",
"ethrex-crypto",
+ "ethrex-p2p",
"ethrex-rlp",
"ethrex-trie",
"hex",
@@ -3962,10 +4029,15 @@ name = "ethrex-rlp"
version = "7.0.0"
dependencies = [
"bytes",
+ "criterion 0.8.0",
"ethereum-types 0.15.1",
+ "ethrex-common",
+ "ethrex-p2p",
+ "ethrex-trie",
"hex",
"hex-literal 0.4.1",
"lazy_static",
+ "rand 0.8.5",
"snap",
"thiserror 2.0.17",
"tinyvec",
@@ -4108,7 +4180,7 @@ dependencies = [
"anyhow",
"bytes",
"cita_trie",
- "criterion",
+ "criterion 0.5.1",
"crossbeam 0.8.4",
"digest 0.10.7",
"ethereum-types 0.15.1",
@@ -9087,6 +9159,16 @@ dependencies = [
"serde",
]
+[[package]]
+name = "page_size"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
[[package]]
name = "pairing"
version = "0.22.0"
diff --git a/Makefile b/Makefile
index e142a77d554..42659110768 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
.PHONY: build lint test clean run-image build-image clean-vectors \
setup-hive test-pattern-default run-hive run-hive-debug clean-hive-logs \
- load-test-fibonacci load-test-io run-hive-eels-blobs
+ load-test-fibonacci load-test-io run-hive-eels-blobs bench-rlp
help: ## 📚 Show help for each of the Makefile recipes
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
@@ -178,6 +178,9 @@ fixtures/ERC20/ERC20.bin: ## 🔨 Build the ERC20 contract for the load test
sort-genesis-files:
cd ./tooling/genesis && cargo run
+bench-rlp: ## âš¡ Bench the RLP decoder/encoder
+ cd ./crates/common/rlp && cargo bench
+
# Using & so make calls this recipe only once per run
mermaid-init.js mermaid.min.js &:
@# Required for mdbook-mermaid to work
diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml
index bc415feb6b0..e17495f25cc 100644
--- a/crates/common/Cargo.toml
+++ b/crates/common/Cargo.toml
@@ -37,6 +37,7 @@ secp256k1 = { workspace = true, optional = true }
[dev-dependencies]
hex-literal.workspace = true
+ethrex-p2p.workspace = true
[features]
default = ["secp256k1"]
diff --git a/crates/common/rlp/Cargo.toml b/crates/common/rlp/Cargo.toml
index d1754a97d86..b5e54456076 100644
--- a/crates/common/rlp/Cargo.toml
+++ b/crates/common/rlp/Cargo.toml
@@ -16,8 +16,22 @@ snap.workspace = true
[dev-dependencies]
hex-literal.workspace = true
+criterion = { version = "0.8.0", features = ["html_reports", "csv_output"] }
+ethrex-common.workspace = true
+ethrex-p2p.workspace = true
+ethrex-trie.workspace = true
+rand.workspace = true
+
[lib]
path = "./rlp.rs"
[lints]
workspace = true
+
+[[bench]]
+name = "decode"
+harness = false
+
+[[bench]]
+name = "encode"
+harness = false
diff --git a/crates/common/rlp/benches/decode.rs b/crates/common/rlp/benches/decode.rs
new file mode 100644
index 00000000000..3bee0894418
--- /dev/null
+++ b/crates/common/rlp/benches/decode.rs
@@ -0,0 +1,36 @@
+use criterion::{Criterion, criterion_group, criterion_main};
+
+fn bench_decode_scalars(c: &mut Criterion) {
+ let mut group = c.benchmark_group("decode_scalars");
+ group.finish();
+}
+
+fn bench_decode_bytes_strings(c: &mut Criterion) {
+ let mut group = c.benchmark_group("decode_bytes_strings");
+ group.finish();
+}
+
+fn bench_decode_collections(c: &mut Criterion) {
+ let mut group = c.benchmark_group("decode_collections");
+ group.finish();
+}
+
+fn bench_decode_tuples(c: &mut Criterion) {
+ let mut group = c.benchmark_group("decode_tuples");
+ group.finish();
+}
+
+fn bench_decode_ips(c: &mut Criterion) {
+ let mut group = c.benchmark_group("decode_ip_types");
+ group.finish();
+}
+
+criterion_group!(
+ benches,
+ bench_decode_scalars,
+ bench_decode_bytes_strings,
+ bench_decode_collections,
+ bench_decode_tuples,
+ bench_decode_ips,
+);
+criterion_main!(benches);
diff --git a/crates/common/rlp/benches/encode.rs b/crates/common/rlp/benches/encode.rs
new file mode 100644
index 00000000000..5247fca134b
--- /dev/null
+++ b/crates/common/rlp/benches/encode.rs
@@ -0,0 +1,1440 @@
+use bytes::Bytes;
+use criterion::{Criterion, Throughput, criterion_group, criterion_main};
+use ethereum_types::U256;
+use ethrex_common::{
+ Address, Bloom, H32, H160, H256, H264, H512,
+ constants::EMPTY_KECCACK_HASH,
+ types::{
+ AccessList, AccountInfo, AccountState, AuthorizationList, AuthorizationTuple,
+ BYTES_PER_BLOB, BlobsBundle, Block, BlockBody, BlockHeader, EIP1559Transaction,
+ EIP2930Transaction, EIP4844Transaction, EIP7702Transaction, FeeTokenTransaction, ForkId,
+ LegacyTransaction, Log, MempoolTransaction, P2PTransaction, PrivilegedL2Transaction,
+ Receipt, ReceiptWithBloom, Transaction, TxKind, TxType, Withdrawal,
+ WrappedEIP4844Transaction, requests::EncodedRequests,
+ },
+};
+use ethrex_p2p::{
+ discv4::messages::{ENRRequestMessage, FindNodeMessage, NeighborsMessage, PingMessage},
+ rlpx::{
+ p2p::Capability,
+ snap::{AccountRangeUnit, AccountStateSlim, StorageSlot},
+ },
+ types::{Endpoint, Node, NodeRecord, NodeRecordPairs},
+};
+use ethrex_rlp::{encode::RLPEncode, structs::Encoder};
+use ethrex_trie::{
+ Nibbles, Node as TrieNode, NodeHash, NodeRef,
+ node::{BranchNode, ExtensionNode, LeafNode},
+};
+use rand::{Rng, SeedableRng, rngs::StdRng};
+use std::{
+ hint::black_box,
+ net::{IpAddr, Ipv4Addr},
+ str::FromStr,
+ time::Duration,
+};
+
+fn make_string_list(count: usize) -> Vec {
+ let entry = "abcdefghij".to_string();
+ vec![entry; count]
+}
+
+fn create_nibbles(len: usize) -> Nibbles {
+ let pattern = (0..len).map(|i| (i % 16) as u8).collect::>();
+ Nibbles::from_hex(pattern)
+}
+
+fn random_u256(rng: &mut StdRng) -> U256 {
+ let bytes: [u8; 32] = rng.r#gen();
+ U256::from_big_endian(&bytes)
+}
+
+fn create_access_list() -> AccessList {
+ vec![(
+ Address::from_str("0x000000000000000000000000000000000000000a").unwrap(),
+ vec![HASH],
+ )]
+}
+
+fn create_authorization_list() -> AuthorizationList {
+ vec![AuthorizationTuple {
+ chain_id: U256::from(1u64),
+ address: Address::from_str("0x00000000000000000000000000000000000000bb").unwrap(),
+ nonce: 1,
+ y_parity: U256::from(1u64),
+ r_signature: U256::from(2u64),
+ s_signature: U256::from(3u64),
+ }]
+}
+
+fn create_endpoint(octet: u8, udp_port: u16, tcp_port: u16) -> Endpoint {
+ Endpoint {
+ ip: IpAddr::V4(Ipv4Addr::new(192, 168, 0, octet)),
+ udp_port,
+ tcp_port,
+ }
+}
+
+fn create_node(index: u8) -> Node {
+ Node::new(
+ IpAddr::V4(Ipv4Addr::new(10, 0, 0, index)),
+ 30_300 + index as u16,
+ 40_400 + index as u16,
+ H512::repeat_byte(index),
+ )
+}
+
+fn create_node_record() -> NodeRecord {
+ let pairs: Vec<(Bytes, Bytes)> = NodeRecordPairs {
+ id: Some("v4".to_string()),
+ ip: Some(Ipv4Addr::new(127, 0, 0, 1)),
+ ip6: None,
+ tcp_port: Some(30303),
+ udp_port: Some(30303),
+ secp256k1: Some(H264::repeat_byte(0x33)),
+ eth: None,
+ }
+ .into();
+
+ NodeRecord {
+ signature: H512::repeat_byte(0x22),
+ seq: 1,
+ pairs,
+ }
+}
+
+static HASH: H256 = H256::repeat_byte(0xab);
+
+fn bench_encode_integer(c: &mut Criterion) {
+ let mut group = c.benchmark_group("basic_types");
+
+ let u8_values = {
+ let mut rng = StdRng::seed_from_u64(1);
+ (0..1_000_000)
+ .map(|_| {
+ let byte: u8 = rng.r#gen();
+ byte & 0x7f
+ })
+ .collect::>()
+ };
+ group.throughput(Throughput::Elements(u8_values.len() as u64));
+ group.bench_function("encode_u8_random_seeded", move |b| {
+ let mut buf = Vec::with_capacity(2 * u8_values.len());
+ b.iter(|| {
+ buf.clear();
+ for &value in &u8_values {
+ value.encode(&mut buf);
+ }
+ black_box(&buf);
+ });
+ });
+
+ let u16_values = {
+ let mut rng = StdRng::seed_from_u64(2);
+ (0..1_000_000)
+ .map(|_| {
+ let value: u16 = rng.r#gen();
+ value % 10_001
+ })
+ .collect::>()
+ };
+ group.throughput(Throughput::Elements(u16_values.len() as u64));
+ group.bench_function("encode_u16_random_seeded", move |b| {
+ let mut buf = Vec::with_capacity(3 * u16_values.len());
+ b.iter(|| {
+ buf.clear();
+ for &value in &u16_values {
+ value.encode(&mut buf);
+ }
+ black_box(&buf);
+ });
+ });
+
+ let u32_values = {
+ let mut rng = StdRng::seed_from_u64(3);
+ (0..1_000_000)
+ .map(|_| {
+ let value: u32 = rng.r#gen();
+ value % 1_000_001
+ })
+ .collect::>()
+ };
+ group.throughput(Throughput::Elements(u32_values.len() as u64));
+ group.bench_function("encode_u32_random_seeded", move |b| {
+ let mut buf = Vec::with_capacity(5 * u32_values.len());
+ b.iter(|| {
+ buf.clear();
+ for &value in &u32_values {
+ value.encode(&mut buf);
+ }
+ black_box(&buf);
+ });
+ });
+
+ let u64_values = {
+ let mut rng = StdRng::seed_from_u64(4);
+ (0..1_000_000)
+ .map(|_| {
+ let value: u64 = rng.r#gen();
+ value % 1_000_000_001
+ })
+ .collect::>()
+ };
+ group.throughput(Throughput::Elements(u64_values.len() as u64));
+ group.bench_function("encode_u64_random_seeded", move |b| {
+ let mut buf = Vec::with_capacity(9 * u64_values.len());
+ b.iter(|| {
+ buf.clear();
+ for &value in &u64_values {
+ value.encode(&mut buf);
+ }
+ black_box(&buf);
+ });
+ });
+
+ let u128_values = {
+ let mut rng = StdRng::seed_from_u64(5);
+ (0..1_000_000).map(|_| rng.r#gen()).collect::>()
+ };
+ group.throughput(Throughput::Elements(u128_values.len() as u64));
+ group.bench_function("encode_u128_random_seeded", move |b| {
+ let mut buf = Vec::with_capacity(17 * u128_values.len());
+ b.iter(|| {
+ buf.clear();
+ for &value in &u128_values {
+ value.encode(&mut buf);
+ }
+ black_box(&buf);
+ });
+ });
+
+ let u256_values = {
+ let mut rng = StdRng::seed_from_u64(6);
+ (0..1_000_000)
+ .map(|_| random_u256(&mut rng))
+ .collect::>()
+ };
+ group.throughput(Throughput::Elements(u256_values.len() as u64));
+ group.bench_function("encode_u256_random_seeded", move |b| {
+ let mut buf = Vec::with_capacity(33 * u256_values.len());
+ b.iter(|| {
+ buf.clear();
+ for value in &u256_values {
+ value.encode(&mut buf);
+ }
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_strings(c: &mut Criterion) {
+ let mut group = c.benchmark_group("basic_types");
+ for &len in &[5usize, 60, 500] {
+ let label = format!("encode_string_len_{len}");
+ let mut rng = StdRng::seed_from_u64(len as u64);
+ let values: Vec = (0..10_000)
+ .map(|_| {
+ let mut s = String::with_capacity(len);
+ for _ in 0..len {
+ s.push(rng.r#gen());
+ }
+ s
+ })
+ .collect();
+ let values = black_box(values);
+ group.throughput(Throughput::Elements(values.len() as u64));
+ group.bench_function(label, move |b| {
+ let mut buf = Vec::with_capacity(values[0].length() * values.len());
+ b.iter(|| {
+ buf.clear();
+ for v in &values {
+ v.encode(&mut buf);
+ }
+ black_box(&buf);
+ });
+ });
+ }
+ group.finish();
+}
+
+fn bench_encode_int_lists(c: &mut Criterion) {
+ let mut group = c.benchmark_group("basic_types");
+ for &count in &[10usize, 100, 1000] {
+ let label = format!("encode_int_list_len_{count}");
+ let mut rng = StdRng::seed_from_u64(count as u64);
+ let values: Vec = (0..count).map(|_| rng.r#gen()).collect();
+ let value = black_box(values);
+ group.throughput(Throughput::Elements(value.len() as u64));
+ group.bench_function(label, move |b| {
+ let mut buf = Vec::with_capacity(value.length());
+ b.iter(|| {
+ buf.clear();
+ value.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+ }
+ group.finish();
+}
+
+fn bench_encode_string_lists(c: &mut Criterion) {
+ let mut group = c.benchmark_group("basic_types");
+ for &count in &[10usize, 100, 1000] {
+ let label = format!("encode_string_list_len_{count}");
+ let value = black_box(make_string_list(count));
+ group.throughput(Throughput::Elements(value.len() as u64));
+ group.bench_function(label, move |b| {
+ let mut buf = Vec::with_capacity(value.length());
+ b.iter(|| {
+ buf.clear();
+ value.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+ }
+ group.finish();
+}
+
+fn bench_encode_account_info(c: &mut Criterion) {
+ let mut group = c.benchmark_group("common_types");
+
+ let account_info = black_box(AccountInfo {
+ code_hash: HASH,
+ balance: U256::from(0xf34ab23u64),
+ nonce: 1,
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_account_info", move |b| {
+ let mut buf = Vec::with_capacity(account_info.length());
+ b.iter(|| {
+ buf.clear();
+ account_info.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_account_state(c: &mut Criterion) {
+ let mut group = c.benchmark_group("common_types");
+
+ let account_state = black_box(AccountState {
+ nonce: 1,
+ balance: U256::from(0xf34ab23u64),
+ storage_root: HASH,
+ code_hash: HASH,
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_account_state", move |b| {
+ let mut buf = Vec::with_capacity(account_state.length());
+ b.iter(|| {
+ buf.clear();
+ account_state.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_tx_kind(c: &mut Criterion) {
+ let mut group = c.benchmark_group("transactions");
+
+ let create_kind = black_box(TxKind::Create);
+ let call_kind = black_box(TxKind::Call(
+ Address::from_str("0x00000000000000000000000000000000000000ff").unwrap(),
+ ));
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_create", move |b| {
+ let mut buf = Vec::with_capacity(create_kind.length());
+ b.iter(|| {
+ buf.clear();
+ create_kind.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_call", move |b| {
+ let mut buf = Vec::new();
+ b.iter(|| {
+ buf.clear();
+ call_kind.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_legacy_transaction(c: &mut Criterion) {
+ let mut group = c.benchmark_group("transactions");
+
+ let legacy_tx = black_box(LegacyTransaction {
+ nonce: 1,
+ gas_price: U256::from(50_000),
+ gas: 21_000,
+ to: TxKind::Create,
+ value: U256::from(1_000_000u64),
+ data: Bytes::from(vec![0u8; 32]),
+ v: U256::from(27u64),
+ r: U256::from(1u64),
+ s: U256::from(2u64),
+ inner_hash: Default::default(),
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_legacy_transaction", move |b| {
+ let mut buf = Vec::with_capacity(legacy_tx.length());
+ b.iter(|| {
+ buf.clear();
+ legacy_tx.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_eip2930_transaction(c: &mut Criterion) {
+ let mut group = c.benchmark_group("transactions");
+
+ let eip2930_tx = black_box(EIP2930Transaction {
+ chain_id: 1,
+ nonce: 2,
+ gas_price: U256::from(30_000),
+ gas_limit: 50_000,
+ to: TxKind::Call(Address::from_str("0x0000000000000000000000000000000000000aaa").unwrap()),
+ value: U256::from(42u64),
+ data: Bytes::from(vec![0x12; 16]),
+ access_list: create_access_list(),
+ signature_y_parity: true,
+ signature_r: U256::from(5u64),
+ signature_s: U256::from(6u64),
+ inner_hash: Default::default(),
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_eip2930_transaction", move |b| {
+ let mut buf = Vec::with_capacity(eip2930_tx.length());
+ b.iter(|| {
+ buf.clear();
+ eip2930_tx.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_eip1559_transaction(c: &mut Criterion) {
+ let mut group = c.benchmark_group("transactions");
+
+ let eip1559_tx = black_box(EIP1559Transaction {
+ chain_id: 1,
+ nonce: 3,
+ max_priority_fee_per_gas: 1,
+ max_fee_per_gas: 100,
+ gas_limit: 100_000,
+ to: TxKind::Create,
+ value: U256::from(900u64),
+ data: Bytes::from(vec![0x34; 24]),
+ access_list: create_access_list(),
+ signature_y_parity: false,
+ signature_r: U256::from(7u64),
+ signature_s: U256::from(8u64),
+ inner_hash: Default::default(),
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_eip1559_transaction", move |b| {
+ let mut buf = Vec::with_capacity(eip1559_tx.length());
+ b.iter(|| {
+ buf.clear();
+ eip1559_tx.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_eip4844_transaction(c: &mut Criterion) {
+ let mut group = c.benchmark_group("transactions");
+
+ let eip4844_tx = EIP4844Transaction {
+ chain_id: 1,
+ nonce: 4,
+ max_priority_fee_per_gas: 2,
+ max_fee_per_gas: 200,
+ gas: 120_000,
+ to: Address::from_str("0x0000000000000000000000000000000000000bbb").unwrap(),
+ value: U256::from(1_500u64),
+ data: Bytes::from(vec![0x56; 48]),
+ access_list: create_access_list(),
+ max_fee_per_blob_gas: U256::from(10u64),
+ blob_versioned_hashes: vec![H256::repeat_byte(0x44)],
+ signature_y_parity: true,
+ signature_r: U256::from(9u64),
+ signature_s: U256::from(10u64),
+ inner_hash: Default::default(),
+ };
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_eip4844_transaction", move |b| {
+ let mut buf = Vec::with_capacity(eip4844_tx.length());
+ b.iter(|| {
+ buf.clear();
+ eip4844_tx.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_wrapped_eip4844_transaction(c: &mut Criterion) {
+ let mut group = c.benchmark_group("transactions");
+
+ let inner_tx = EIP4844Transaction {
+ chain_id: 1,
+ nonce: 5,
+ max_priority_fee_per_gas: 3,
+ max_fee_per_gas: 300,
+ gas: 130_000,
+ to: Address::from_str("0x0000000000000000000000000000000000000ccc").unwrap(),
+ value: U256::from(2_500u64),
+ data: Bytes::from(vec![0x78; 64]),
+ access_list: create_access_list(),
+ max_fee_per_blob_gas: U256::from(12u64),
+ blob_versioned_hashes: vec![H256::repeat_byte(0x55); 2],
+ signature_y_parity: true,
+ signature_r: U256::from(11u64),
+ signature_s: U256::from(12u64),
+ inner_hash: Default::default(),
+ };
+
+ let blobs_bundle = BlobsBundle {
+ blobs: vec![[7u8; BYTES_PER_BLOB]; 2],
+ commitments: vec![[0x23u8; 48]; 2],
+ proofs: vec![[0x34u8; 48]; 2],
+ version: 1,
+ };
+
+ let wrapped = black_box(WrappedEIP4844Transaction {
+ tx: black_box(inner_tx),
+ wrapper_version: Some(1),
+ blobs_bundle,
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_wrapped_eip4844_transaction", move |b| {
+ let mut buf = Vec::with_capacity(wrapped.length());
+ b.iter(|| {
+ buf.clear();
+ wrapped.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_eip7702_transaction(c: &mut Criterion) {
+ let mut group = c.benchmark_group("transactions");
+
+ let eip7702_tx = black_box(EIP7702Transaction {
+ chain_id: 1,
+ nonce: 6,
+ max_priority_fee_per_gas: 4,
+ max_fee_per_gas: 400,
+ gas_limit: 140_000,
+ to: Address::from_str("0x0000000000000000000000000000000000000ddd").unwrap(),
+ value: U256::from(3_500u64),
+ data: Bytes::from(vec![0x9a; 72]),
+ access_list: create_access_list(),
+ authorization_list: create_authorization_list(),
+ signature_y_parity: false,
+ signature_r: U256::from(13u64),
+ signature_s: U256::from(14u64),
+ inner_hash: Default::default(),
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_eip7702_transaction", move |b| {
+ let mut buf = Vec::with_capacity(eip7702_tx.length());
+ b.iter(|| {
+ buf.clear();
+ eip7702_tx.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_privileged_l2_transaction(c: &mut Criterion) {
+ let mut group = c.benchmark_group("transactions");
+
+ let privileged_tx = black_box(PrivilegedL2Transaction {
+ chain_id: 1,
+ nonce: 7,
+ max_priority_fee_per_gas: 5,
+ max_fee_per_gas: 500,
+ gas_limit: 150_000,
+ to: TxKind::Create,
+ value: U256::from(4_500u64),
+ data: Bytes::from(vec![0xbc; 40]),
+ access_list: create_access_list(),
+ from: Address::from_str("0x0000000000000000000000000000000000000eee").unwrap(),
+ inner_hash: Default::default(),
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_privileged_l2_transaction", move |b| {
+ let mut buf = Vec::with_capacity(privileged_tx.length());
+ b.iter(|| {
+ buf.clear();
+ privileged_tx.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_fee_token_transaction(c: &mut Criterion) {
+ let mut group = c.benchmark_group("transactions");
+
+ let fee_token_tx = black_box(FeeTokenTransaction {
+ chain_id: 1,
+ nonce: 8,
+ max_priority_fee_per_gas: 6,
+ max_fee_per_gas: 600,
+ gas_limit: 160_000,
+ to: TxKind::Call(Address::from_str("0x0000000000000000000000000000000000000fff").unwrap()),
+ value: U256::from(5_500u64),
+ data: Bytes::from(vec![0xde; 44]),
+ access_list: create_access_list(),
+ fee_token: Address::from_str("0x0000000000000000000000000000000000000fed").unwrap(),
+ signature_y_parity: true,
+ signature_r: U256::from(15u64),
+ signature_s: U256::from(16u64),
+ inner_hash: Default::default(),
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_fee_token_transaction", move |b| {
+ let mut buf = Vec::with_capacity(fee_token_tx.length());
+ b.iter(|| {
+ buf.clear();
+ fee_token_tx.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_p2p_transaction(c: &mut Criterion) {
+ let mut group = c.benchmark_group("transactions");
+
+ let wrapped_tx = black_box(WrappedEIP4844Transaction {
+ tx: EIP4844Transaction {
+ chain_id: 1,
+ nonce: 9,
+ max_priority_fee_per_gas: 7,
+ max_fee_per_gas: 700,
+ gas: 170_000,
+ to: Address::from_str("0x0000000000000000000000000000000000000abc").unwrap(),
+ value: U256::from(6_500u64),
+ data: Bytes::from(vec![0xef; 52]),
+ access_list: create_access_list(),
+ max_fee_per_blob_gas: U256::from(18u64),
+ blob_versioned_hashes: vec![H256::repeat_byte(0x66)],
+ signature_y_parity: false,
+ signature_r: U256::from(17u64),
+ signature_s: U256::from(18u64),
+ inner_hash: Default::default(),
+ },
+ wrapper_version: Some(1),
+ blobs_bundle: BlobsBundle {
+ blobs: vec![[8u8; BYTES_PER_BLOB]],
+ commitments: vec![[0x44u8; 48]],
+ proofs: vec![[0x55u8; 48]],
+ version: 1,
+ },
+ });
+
+ let p2p_tx = P2PTransaction::EIP4844TransactionWithBlobs(wrapped_tx);
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_p2p_transaction", move |b| {
+ let mut buf = Vec::with_capacity(p2p_tx.length());
+ b.iter(|| {
+ buf.clear();
+ p2p_tx.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_mempool_transaction(c: &mut Criterion) {
+ let mut group = c.benchmark_group("transactions");
+
+ let tx = black_box(Transaction::EIP1559Transaction(EIP1559Transaction {
+ chain_id: 1,
+ nonce: 10,
+ max_priority_fee_per_gas: 8,
+ max_fee_per_gas: 800,
+ gas_limit: 180_000,
+ to: TxKind::Create,
+ value: U256::from(7_500u64),
+ data: Bytes::from(vec![0xaa; 36]),
+ access_list: create_access_list(),
+ signature_y_parity: true,
+ signature_r: U256::from(19u64),
+ signature_s: U256::from(20u64),
+ inner_hash: Default::default(),
+ }));
+ let mempool_tx = black_box(MempoolTransaction::new(
+ tx,
+ Address::from_str("0x0000000000000000000000000000000000000cab").unwrap(),
+ ));
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_mempool_transaction", move |b| {
+ let mut buf = Vec::with_capacity(mempool_tx.length());
+ b.iter(|| {
+ buf.clear();
+ mempool_tx.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_p2p_endpoint(c: &mut Criterion) {
+ let mut group = c.benchmark_group("networking_p2p");
+
+ let endpoint = create_endpoint(10, 30303, 30303);
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_endpoint", move |b| {
+ let mut buf = Vec::with_capacity(endpoint.length());
+ b.iter(|| {
+ buf.clear();
+ endpoint.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_p2p_node(c: &mut Criterion) {
+ let mut group = c.benchmark_group("networking_p2p");
+
+ let node = create_node(1);
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_node", move |b| {
+ let mut buf = Vec::with_capacity(node.length());
+ b.iter(|| {
+ buf.clear();
+ node.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_node_record(c: &mut Criterion) {
+ let mut group = c.benchmark_group("networking_p2p");
+
+ let node_record = create_node_record();
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_node_record", move |b| {
+ let mut buf = Vec::with_capacity(node_record.length());
+ b.iter(|| {
+ buf.clear();
+ node_record.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_ping_message(c: &mut Criterion) {
+ let mut group = c.benchmark_group("networking_p2p");
+
+ let from = create_endpoint(1, 30301, 30301);
+ let to = create_endpoint(2, 30302, 30302);
+ let ping = PingMessage::new(from, to, 1_700_000_000).with_enr_seq(42);
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_ping_message", move |b| {
+ let mut buf = Vec::with_capacity(ping.length());
+ b.iter(|| {
+ buf.clear();
+ ping.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_find_node_message(c: &mut Criterion) {
+ let mut group = c.benchmark_group("networking_p2p");
+
+ let msg = FindNodeMessage::new(H512::repeat_byte(0x77), 1_700_000_000);
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_find_node_message", move |b| {
+ let mut buf = Vec::with_capacity(msg.length());
+ b.iter(|| {
+ buf.clear();
+ msg.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_neighbors_message(c: &mut Criterion) {
+ let mut group = c.benchmark_group("networking_p2p");
+
+ let neighbors = NeighborsMessage::new(vec![create_node(3), create_node(4)], 1_700_000_000);
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_neighbors_message", move |b| {
+ let mut buf = Vec::with_capacity(neighbors.length());
+ b.iter(|| {
+ buf.clear();
+ neighbors.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_enr_request_message(c: &mut Criterion) {
+ let mut group = c.benchmark_group("networking_p2p");
+
+ let msg = ENRRequestMessage::new(1_700_000_000);
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_enr_request_message", move |b| {
+ let mut buf = Vec::with_capacity(msg.length());
+ b.iter(|| {
+ buf.clear();
+ msg.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_capability(c: &mut Criterion) {
+ let mut group = c.benchmark_group("networking_p2p");
+
+ let capability = Capability::eth(68);
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_capability", move |b| {
+ let mut buf = Vec::with_capacity(capability.length());
+ b.iter(|| {
+ buf.clear();
+ capability.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_account_state_slim(c: &mut Criterion) {
+ let mut group = c.benchmark_group("networking_p2p");
+
+ let account_state = black_box(AccountStateSlim {
+ nonce: 1,
+ balance: U256::from(1000u64),
+ storage_root: Bytes::from(vec![0xaa; 32]),
+ code_hash: Bytes::from(vec![0xbb; 32]),
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_account_state_slim", move |b| {
+ let mut buf = Vec::with_capacity(account_state.length());
+ b.iter(|| {
+ buf.clear();
+ account_state.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_account_range_unit(c: &mut Criterion) {
+ let mut group = c.benchmark_group("networking_p2p");
+
+ let account_state = black_box(AccountStateSlim {
+ nonce: 2,
+ balance: U256::from(2_000u64),
+ storage_root: Bytes::from(vec![0xcc; 32]),
+ code_hash: Bytes::from(vec![0xdd; 32]),
+ });
+
+ let unit = black_box(AccountRangeUnit {
+ hash: H256::repeat_byte(0x99),
+ account: account_state,
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_account_range_unit", move |b| {
+ let mut buf = Vec::with_capacity(unit.length());
+ b.iter(|| {
+ buf.clear();
+ unit.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_storage_slot(c: &mut Criterion) {
+ let mut group = c.benchmark_group("networking_p2p");
+
+ let slot = black_box(StorageSlot {
+ hash: H256::repeat_byte(0x42),
+ data: U256::from(1234u64),
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_storage_slot", move |b| {
+ let mut buf = Vec::with_capacity(slot.length());
+ b.iter(|| {
+ buf.clear();
+ slot.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_nibbles(c: &mut Criterion) {
+ let mut group = c.benchmark_group("trie");
+ for &len in &[65usize, 129, 130, 500] {
+ let label = format!("encode_nibbles_len_{len}");
+ let nibbles = black_box(create_nibbles(len));
+ group.throughput(Throughput::Elements(1));
+ group.bench_function(label, move |b| {
+ let mut buf = Vec::with_capacity(nibbles.length());
+ b.iter(|| {
+ buf.clear();
+ nibbles.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+ }
+ group.finish();
+}
+
+fn bench_encode_node_hash(c: &mut Criterion) {
+ let mut group = c.benchmark_group("trie");
+
+ let inline_hash = {
+ let mut data = [0u8; 31];
+ data[..10].fill(0x2a);
+ NodeHash::Inline((data, 10))
+ };
+ let hashed_hash = NodeHash::from(H256::repeat_byte(0x42));
+
+ for (label, node_hash) in [
+ ("encode_node_hash_inline", inline_hash),
+ ("encode_node_hash_hashed", hashed_hash),
+ ] {
+ let node_hash = black_box(node_hash);
+ group.throughput(Throughput::Elements(1));
+ group.bench_function(label, move |b| {
+ let mut buf = Vec::with_capacity(node_hash.length());
+ b.iter(|| {
+ buf.clear();
+ let encoder = node_hash.encode(Encoder::new(&mut buf));
+ black_box(&encoder);
+ black_box(&buf);
+ });
+ });
+ }
+
+ group.finish();
+}
+
+fn bench_encode_branch_node(c: &mut Criterion) {
+ let mut group = c.benchmark_group("trie");
+
+ let mut choices = BranchNode::EMPTY_CHOICES;
+ choices[0] = NodeHash::from(H256::repeat_byte(0x11)).into();
+ choices[1] = TrieNode::from(LeafNode::new(create_nibbles(6), vec![0x33; 12])).into();
+ choices[15] = NodeHash::from(H256::repeat_byte(0xaa)).into();
+
+ let branch = black_box(BranchNode {
+ choices,
+ value: vec![0x55; 32],
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_branch_node", move |b| {
+ let mut buf = Vec::with_capacity(branch.length());
+ b.iter(|| {
+ buf.clear();
+ branch.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_extension_node(c: &mut Criterion) {
+ let mut group = c.benchmark_group("trie");
+
+ let extension = black_box(ExtensionNode {
+ prefix: create_nibbles(20),
+ child: NodeRef::from(NodeHash::from(H256::repeat_byte(0x53))),
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_extension_node", move |b| {
+ let mut buf = Vec::with_capacity(extension.length());
+ b.iter(|| {
+ buf.clear();
+ extension.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_leaf_node(c: &mut Criterion) {
+ let mut group = c.benchmark_group("trie");
+
+ let leaf = black_box(LeafNode::new(create_nibbles(18), vec![0x44; 40]));
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_leaf_node", move |b| {
+ let mut buf = Vec::with_capacity(leaf.length());
+ b.iter(|| {
+ buf.clear();
+ leaf.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_fork_id(c: &mut Criterion) {
+ let mut group = c.benchmark_group("common_types");
+
+ let fork_id = black_box(ForkId {
+ fork_hash: H32::from_slice(&[0xde, 0xad, 0xbe, 0xef]),
+ fork_next: 17_000_000,
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_fork_id", move |b| {
+ let mut buf = Vec::with_capacity(fork_id.length());
+ b.iter(|| {
+ buf.clear();
+ fork_id.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_log(c: &mut Criterion) {
+ let mut group = c.benchmark_group("common_types");
+
+ let log_entry = black_box(Log {
+ address: Address::from_str("0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba").unwrap(),
+ topics: vec![HASH, H256::repeat_byte(0x11), H256::repeat_byte(0x22)],
+ data: Bytes::from(vec![0x55; 128]),
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_log", move |b| {
+ let mut buf = Vec::with_capacity(log_entry.length());
+ b.iter(|| {
+ buf.clear();
+ log_entry.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_receipt(c: &mut Criterion) {
+ let mut group = c.benchmark_group("common_types");
+
+ let receipt_logs = black_box(vec![
+ Log {
+ address: Address::from_str("0x1000000000000000000000000000000000000001").unwrap(),
+ topics: vec![HASH, H256::repeat_byte(0x33)],
+ data: Bytes::from(vec![0xaa; 96]),
+ },
+ Log {
+ address: Address::from_str("0x2000000000000000000000000000000000000002").unwrap(),
+ topics: vec![H256::repeat_byte(0xbb)],
+ data: Bytes::from(vec![0xbb; 64]),
+ },
+ ]);
+
+ let receipt = black_box(Receipt {
+ tx_type: TxType::EIP1559,
+ succeeded: true,
+ cumulative_gas_used: 120_000,
+ logs: receipt_logs,
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_receipt", move |b| {
+ let mut buf = Vec::with_capacity(receipt.length());
+ b.iter(|| {
+ buf.clear();
+ receipt.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_receipt_with_bloom(c: &mut Criterion) {
+ let mut group = c.benchmark_group("common_types");
+
+ let logs_with_bloom = black_box(vec![
+ Log {
+ address: Address::from_str("0x3000000000000000000000000000000000000003").unwrap(),
+ topics: vec![H256::repeat_byte(0x44), H256::repeat_byte(0x55)],
+ data: Bytes::from(vec![0xcc; 80]),
+ },
+ Log {
+ address: Address::from_str("0x4000000000000000000000000000000000000004").unwrap(),
+ topics: vec![HASH],
+ data: Bytes::from(vec![0xdd; 48]),
+ },
+ ]);
+
+ let receipt = black_box(ReceiptWithBloom::new(
+ TxType::EIP4844,
+ true,
+ 240_000,
+ logs_with_bloom,
+ ));
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_receipt_with_bloom", move |b| {
+ let mut buf = Vec::with_capacity(receipt.length());
+ b.iter(|| {
+ buf.clear();
+ receipt.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_encoded_requests(c: &mut Criterion) {
+ let mut group = c.benchmark_group("common_types");
+
+ let mut request_bytes: Vec = (0..192).map(|i| i as u8).collect();
+ request_bytes.insert(0, 0x00);
+ let encoded_requests = black_box(EncodedRequests(Bytes::from(request_bytes)));
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_encoded_requests", move |b| {
+ let mut buf = Vec::with_capacity(encoded_requests.length());
+ b.iter(|| {
+ buf.clear();
+ encoded_requests.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_blobs_bundle(c: &mut Criterion) {
+ let mut group = c.benchmark_group("common_types");
+
+ let blobs_bundle = black_box(BlobsBundle {
+ blobs: vec![[6u8; BYTES_PER_BLOB]; 4],
+ commitments: vec![[0x78u8; 48]],
+ proofs: vec![[0x78u8; 48]],
+ version: 1,
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_blobs_bundle", move |b| {
+ let mut buf = Vec::with_capacity(blobs_bundle.length());
+ b.iter(|| {
+ buf.clear();
+ blobs_bundle.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_block_header(c: &mut Criterion) {
+ let mut group = c.benchmark_group("common_types");
+
+ let block_header = black_box(BlockHeader {
+ parent_hash: H256::from_str(
+ "0x48e29e7357408113a4166e04e9f1aeff0680daa2b97ba93df6512a73ddf7a154",
+ )
+ .unwrap(),
+ ommers_hash: H256::from_str(
+ "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ )
+ .unwrap(),
+ coinbase: Address::from_str("0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba").unwrap(),
+ state_root: H256::from_str(
+ "0x9de6f95cb4ff4ef22a73705d6ba38c4b927c7bca9887ef5d24a734bb863218d9",
+ )
+ .unwrap(),
+ transactions_root: H256::from_str(
+ "0x578602b2b7e3a3291c3eefca3a08bc13c0d194f9845a39b6f3bcf843d9fed79d",
+ )
+ .unwrap(),
+ receipts_root: H256::from_str(
+ "0x035d56bac3f47246c5eed0e6642ca40dc262f9144b582f058bc23ded72aa72fa",
+ )
+ .unwrap(),
+ logs_bloom: Bloom::from([0; 256]),
+ difficulty: U256::zero(),
+ number: 1,
+ gas_limit: 0x016345785d8a0000,
+ gas_used: 0xa8de,
+ timestamp: 0x03e8,
+ extra_data: Bytes::new(),
+ prev_randao: H256::zero(),
+ nonce: 0x0000000000000000,
+ base_fee_per_gas: Some(0x07),
+ withdrawals_root: Some(
+ H256::from_str("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
+ .unwrap(),
+ ),
+ blob_gas_used: Some(0x00),
+ excess_blob_gas: Some(0x00),
+ parent_beacon_block_root: Some(H256::zero()),
+ requests_hash: Some(*EMPTY_KECCACK_HASH),
+ ..Default::default()
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_block_header", move |b| {
+ let mut buf = Vec::with_capacity(block_header.length());
+ b.iter(|| {
+ buf.clear();
+ block_header.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_block(c: &mut Criterion) {
+ let mut group = c.benchmark_group("common_types");
+
+ let block_header = BlockHeader {
+ parent_hash: H256::from_str(
+ "0x48e29e7357408113a4166e04e9f1aeff0680daa2b97ba93df6512a73ddf7a154",
+ )
+ .unwrap(),
+ ommers_hash: H256::from_str(
+ "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
+ )
+ .unwrap(),
+ coinbase: Address::from_str("0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba").unwrap(),
+ state_root: H256::from_str(
+ "0x9de6f95cb4ff4ef22a73705d6ba38c4b927c7bca9887ef5d24a734bb863218d9",
+ )
+ .unwrap(),
+ transactions_root: H256::from_str(
+ "0x578602b2b7e3a3291c3eefca3a08bc13c0d194f9845a39b6f3bcf843d9fed79d",
+ )
+ .unwrap(),
+ receipts_root: H256::from_str(
+ "0x035d56bac3f47246c5eed0e6642ca40dc262f9144b582f058bc23ded72aa72fa",
+ )
+ .unwrap(),
+ logs_bloom: Bloom::from([0; 256]),
+ difficulty: U256::zero(),
+ number: 1,
+ gas_limit: 0x016345785d8a0000,
+ gas_used: 0xa8de,
+ timestamp: 0x03e8,
+ extra_data: Bytes::new(),
+ prev_randao: H256::zero(),
+ nonce: 0x0000000000000000,
+ base_fee_per_gas: Some(0x07),
+ withdrawals_root: Some(
+ H256::from_str("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
+ .unwrap(),
+ ),
+ blob_gas_used: Some(0x00),
+ excess_blob_gas: Some(0x00),
+ parent_beacon_block_root: Some(H256::zero()),
+ requests_hash: Some(*EMPTY_KECCACK_HASH),
+ ..Default::default()
+ };
+
+ let encoded_transactions = [
+ "0x01f8d68330182404842daf517a830186a08080b880c1597f3c842558e64df52c3e0f0973067577c030c0c6578dbb2eef63155a21106fd4426057527f296b2ecdfabc81e34ffc82e89dec20f6b7c41fa1969d3c3bc44262c86f08b5b76077527fb7ece918787c50c878052c30a8b1d4abc07331e6d14b8ded52bbc58a6e9992b76097527f0110937c38cc13b914f201fc09dc6f7a80c001a09930cb92b4a27dce971c697a8c47fa34c98d076abc7b36e1239d6abcfc7c8403a041b35118447fe77c38c0b3a92a2dd3ecba4a9e4b35cc6534cd787f56c0cf2e21",
+ "0xf86e81fa843127403882f61894db8d964741c53e55df9c2d4e9414c6c96482874e870aa87bee538000808360306ca03aa421df67a101c45ff9cb06ce28f518a5d8d8dbb76a79361280071909650a27a05a447ff053c4ae601cfe81859b58d5603f2d0a73481c50f348089032feb0b073",
+ "0x02f8ef83301824048413f157f8842daf517a830186a094000000000000000000000000000000000000000080b8807a0a600060a0553db8600060c855c77fb29ecd7661d8aefe101a0db652a728af0fded622ff55d019b545d03a7532932a60ad52604260cd5360bf60ce53609460cf53603e60d05360f560d153bc596000609e55600060c6556000601f556000609155535660556057536055605853606e60595360e7605a5360d0605b5360eb60c080a03acb03b1fc20507bc66210f7e18ff5af65038fb22c626ae488ad9513d9b6debca05d38459e9d2a221eb345b0c2761b719b313d062ff1ea3d10cf5b8762c44385a6",
+ "0x01f8ea8330182402842daf517a830186a094000000000000000000000000000000000000000080b880bdb30d976000604e557145600060a155d67fe7e473caf6e33cba341136268fc1189ba07837ef8a266570289ff53afc43436260c7527f333dfe837f4838f6053e5e46e4151aeec28f356ec39a2db9769f36ec92e3e3f660e7527f0b261608674300d4621eff679096a6ed786591aca69f2b22a3ea6949621daade610107527f3cc080a01f3f906540fb56b0576c51b3ffa86df213fd1f407378c9441cfdd9d5f3c1df3da035691b16c053b68ec74683ae020293cbc6a47ac773dc8defb96cb680c576e5a3",
+ ];
+ let transactions: Vec = encoded_transactions
+ .iter()
+ .map(|hex| {
+ Transaction::decode_canonical(&hex::decode(hex.trim_start_matches("0x")).unwrap())
+ .unwrap()
+ })
+ .collect();
+
+ let block = black_box(Block {
+ header: block_header.clone(),
+ body: BlockBody {
+ transactions: transactions,
+ ommers: vec![block_header],
+ withdrawals: Some(vec![
+ Withdrawal {
+ index: 0x00,
+ validator_index: 0x00,
+ address: H160::repeat_byte(0xf9),
+ amount: 0x00_u64,
+ };
+ 4
+ ]),
+ },
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_block", move |b| {
+ let mut buf = Vec::with_capacity(block.length());
+ b.iter(|| {
+ buf.clear();
+ block.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn bench_encode_withdrawals(c: &mut Criterion) {
+ let mut group = c.benchmark_group("common_types");
+
+ let withdrawal = black_box(Withdrawal {
+ index: 0x00,
+ validator_index: 0x00,
+ address: H160::repeat_byte(0xf9),
+ amount: 0x80_u64,
+ });
+
+ group.throughput(Throughput::Elements(1));
+ group.bench_function("encode_withdrawals", move |b| {
+ let mut buf = Vec::with_capacity(withdrawal.length());
+ b.iter(|| {
+ buf.clear();
+ withdrawal.encode(&mut buf);
+ black_box(&buf);
+ });
+ });
+
+ group.finish();
+}
+
+fn criterion_config() -> Criterion {
+ Criterion::default()
+ .sample_size(200)
+ .warm_up_time(Duration::from_secs(3))
+ .measurement_time(Duration::from_secs(10))
+}
+
+criterion_group!(
+ name = benches;
+ config = criterion_config();
+ targets = bench_encode_integer,
+ bench_encode_strings,
+ bench_encode_int_lists,
+ bench_encode_string_lists,
+ bench_encode_account_info,
+ bench_encode_account_state,
+ bench_encode_p2p_endpoint,
+ bench_encode_p2p_node,
+ bench_encode_node_record,
+ bench_encode_ping_message,
+ bench_encode_find_node_message,
+ bench_encode_neighbors_message,
+ bench_encode_enr_request_message,
+ bench_encode_capability,
+ bench_encode_account_state_slim,
+ bench_encode_account_range_unit,
+ bench_encode_storage_slot,
+ bench_encode_nibbles,
+ bench_encode_node_hash,
+ bench_encode_branch_node,
+ bench_encode_extension_node,
+ bench_encode_leaf_node,
+ bench_encode_tx_kind,
+ bench_encode_legacy_transaction,
+ bench_encode_eip2930_transaction,
+ bench_encode_eip1559_transaction,
+ bench_encode_eip4844_transaction,
+ bench_encode_wrapped_eip4844_transaction,
+ bench_encode_eip7702_transaction,
+ bench_encode_privileged_l2_transaction,
+ bench_encode_fee_token_transaction,
+ bench_encode_p2p_transaction,
+ bench_encode_mempool_transaction,
+ bench_encode_fork_id,
+ bench_encode_log,
+ bench_encode_receipt,
+ bench_encode_receipt_with_bloom,
+ bench_encode_encoded_requests,
+ bench_encode_blobs_bundle,
+ bench_encode_block_header,
+ bench_encode_block,
+ bench_encode_withdrawals
+);
+criterion_main!(benches);
diff --git a/tooling/Cargo.lock b/tooling/Cargo.lock
index fceb0ba508c..d07812df1e2 100644
--- a/tooling/Cargo.lock
+++ b/tooling/Cargo.lock
@@ -238,6 +238,12 @@ dependencies = [
"libc",
]
+[[package]]
+name = "anes"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
+
[[package]]
name = "ansi_term"
version = "0.12.1"
@@ -1338,6 +1344,12 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
+[[package]]
+name = "cast"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
+
[[package]]
name = "castaway"
version = "0.2.4"
@@ -1811,6 +1823,39 @@ dependencies = [
"cfg-if 1.0.4",
]
+[[package]]
+name = "criterion"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928"
+dependencies = [
+ "anes",
+ "cast",
+ "ciborium",
+ "clap 4.5.51",
+ "criterion-plot",
+ "itertools 0.13.0",
+ "num-traits",
+ "oorandom",
+ "plotters",
+ "rayon",
+ "regex",
+ "serde",
+ "serde_json",
+ "tinytemplate",
+ "walkdir",
+]
+
+[[package]]
+name = "criterion-plot"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338"
+dependencies = [
+ "cast",
+ "itertools 0.13.0",
+]
+
[[package]]
name = "crossbeam"
version = "0.7.3"
@@ -6158,6 +6203,12 @@ version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
+[[package]]
+name = "oorandom"
+version = "11.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
+
[[package]]
name = "opaque-debug"
version = "0.3.1"
@@ -6887,6 +6938,34 @@ version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+[[package]]
+name = "plotters"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
+dependencies = [
+ "num-traits",
+ "plotters-backend",
+ "plotters-svg",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "plotters-backend"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
+
+[[package]]
+name = "plotters-svg"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
+dependencies = [
+ "plotters-backend",
+]
+
[[package]]
name = "portable-atomic"
version = "1.11.1"
@@ -7921,6 +8000,13 @@ dependencies = [
"syn 1.0.109",
]
+[[package]]
+name = "rlp_bench"
+version = "4.0.0"
+dependencies = [
+ "criterion",
+]
+
[[package]]
name = "rocksdb"
version = "0.24.0"
@@ -9814,6 +9900,16 @@ dependencies = [
"zerovec",
]
+[[package]]
+name = "tinytemplate"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
+dependencies = [
+ "serde",
+ "serde_json",
+]
+
[[package]]
name = "tinyvec"
version = "1.10.0"