Skip to content

benches: json-abi + rlp #216

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
May 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 43 additions & 21 deletions benches/BENCHMARKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,59 @@
## Table of Contents

- [Benchmark Results](#benchmark-results)
- [Dynamic](#dynamic)
- [Static](#static)
- [UNIV2: Get Amount In](#univ2:-get-amount-in)
- [UNIV2: Get Amount Out](#univ2:-get-amount-out)
- [ABI Encoding](#abi-encoding)
- [JSON-ABI Serialization](#json-abi-serialization)
- [JSON-ABI Deserialization](#json-abi-deserialization)
- [Serde Function Signature](#serde-function-signature)
- [Rlp Encoding and Decoding](#rlp-encoding-and-decoding)
- [U256 Operations](#u256-operations)

## Benchmark Results

### Dynamic
### ABI Encoding

| | `Ethers` | `Alloy` |
|:-------|:------------------------|:------------------------------- |
| | `2.12 us` (✅ **1.00x**) | `1.76 us` (✅ **1.20x faster**) |
| | `Ethers` | `Alloy` |
| :------------ | :----------------------- | :-------------------------------- |
| **`Static`** | `1.12 us` (✅ **1.00x**) | `90.89 ns` (🚀 **12.32x faster**) |
| **`Dynamic`** | `2.20 us` (✅ **1.00x**) | `1.88 us` (✅ **1.17x faster**) |

### Static
### JSON-ABI Serialization

| | `Ethers` | `Alloy` |
|:-------|:--------------------------|:--------------------------------- |
| | `999.83 ns` (✅ **1.00x**) | `90.87 ns` (🚀 **11.00x faster**) |
| | `EthAbi` | `Alloy` |
| :------------------ | :------------------------ | :------------------------------- |
| **`Seaport`** | `35.43 us` (✅ **1.00x**) | `38.68 us` (✅ **1.09x slower**) |
| **`PoolManager`** | `18.33 us` (✅ **1.00x**) | `17.94 us` (✅ **1.02x faster**) |
| **`UniswapV3Pool`** | `14.61 us` (✅ **1.00x**) | `12.99 us` (✅ **1.12x faster**) |

### UNIV2: Get Amount In
### JSON-ABI Deserialization

| | `Ethers` | `Alloy` |
|:-------|:--------------------------|:--------------------------------- |
| | `503.52 ns` (✅ **1.00x**) | `245.98 ns` (🚀 **2.05x faster**) |
| | `EthAbi` | `Alloy` |
| :------------------ | :------------------------- | :-------------------------------- |
| **`Seaport`** | `209.43 us` (✅ **1.00x**) | `210.67 us` (✅ **1.01x slower**) |
| **`PoolManager`** | `89.05 us` (✅ **1.00x**) | `93.31 us` (✅ **1.05x slower**) |
| **`UniswapV3Pool`** | `63.24 us` (✅ **1.00x**) | `68.50 us` (✅ **1.08x slower**) |

### UNIV2: Get Amount Out
### Serde Function Signature

| | `Ethers` | `Alloy` |
|:-------|:-------------------------|:-------------------------------- |
| | `53.75 ns` (✅ **1.00x**) | `18.22 ns` (🚀 **2.95x faster**) |
| | `EthAbi` | `Alloy` |
| :---------------- | :------------------------ | :--------------------------------- |
| **`Serialize`** | `5.03 us` (✅ **1.00x**) | `247.82 ns` (🚀 **20.29x faster**) |
| **`Deserialize`** | `14.10 us` (✅ **1.00x**) | `14.05 us` (✅ **1.00x faster**) |

### Rlp Encoding and Decoding

| | `Parity-Rlp` | `Alloy-Rlp` |
| :------------- | :------------------------ | :------------------------------- |
| **`Encoding`** | `86.70 ns` (✅ **1.00x**) | `26.88 ns` (🚀 **3.23x faster**) |
| **`Decoding`** | `88.79 ns` (✅ **1.00x**) | `21.43 ns` (🚀 **4.14x faster**) |

### U256 Operations

| | `Ethers` | `Alloy` |
| :-------------- | :------------------------- | :-------------------------------- |
| **`amountIn`** | `512.47 ns` (✅ **1.00x**) | `216.32 ns` (🚀 **2.37x faster**) |
| **`amountOut`** | `53.82 ns` (✅ **1.00x**) | `18.19 ns` (🚀 **2.96x faster**) |

---
Made with [criterion-table](https://github.com/nu11ptr/criterion-table)

Made with [criterion-table](https://github.com/nu11ptr/criterion-table)
14 changes: 11 additions & 3 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,27 @@ ethers.workspace = true
eyre.workspace = true
serde_json.workspace = true
tokio.workspace = true
ethabi = "18"
rlp = "0.6.1"
rlp-derive = "0.2.0"
alloy-rlp = "0.3.11"

[lib]
name = "alloy_benches"
path = "src/lib.rs"

[[bench]]
name = "static_encoding"
name = "abi_encoding"
harness = false

[[bench]]
name = "dyn_encoding"
name = "u256"
harness = false

[[bench]]
name = "u256"
name = "json_abi"
harness = false

[[bench]]
name = "rlp"
harness = false
77 changes: 55 additions & 22 deletions benches/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
## Table of Contents

- [ABI Encoding](#abi-encoding)
- [Dynamic ABI Encoding](#dynamic)
- [Static ABIEncoding](#static)
- [U256 Operations](#u256-operations)
- [UNIV2: Get Amount In](#univ2:-get-amount-in)
- [UNIV2: Get Amount Out](#univ2:-get-amount-out)
- [Rlp Encoding and Decoding](#rlp-encoding-and-decoding)
- [JSON-ABI](#json-abi)
- [Serialization](#serialization)
- [Deserialization](#deserialization)

## ABI Encoding

Expand All @@ -17,30 +17,63 @@ For this benchmark, we are abi-encoding the [`swap` function call](https://githu
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
```

### Dynamic
| | `Ethers` | `Alloy` |
| :------------ | :----------------------- | :-------------------------------- |
| **`Static`** | `1.12 us` (✅ **1.00x**) | `90.89 ns` (🚀 **12.32x faster**) |
| **`Dynamic`** | `2.20 us` (✅ **1.00x**) | `1.88 us` (✅ **1.17x faster**) |

| | `Ethers` | `Alloy` |
| :-- | :----------------------- | :------------------------------ |
| | `2.12 us` (✅ **1.00x**) | `1.76 us` (✅ **1.20x faster**) |
## U256 Operations

### Static
For this benchmark, we are computing the `amountIn` and `amountOut` for the [`swap` function call](https://github.com/Uniswap/v2-core/blob/ee547b17853e71ed4e0101ccfd52e70d5acded58/contracts/UniswapV2Pair.sol#L159) from the current reserves of the Uniswap V2 pair, demonstrating the use of `U256` operations.

| | `Ethers` | `Alloy` |
| :-- | :------------------------- | :-------------------------------- |
| | `999.83 ns` (✅ **1.00x**) | `90.87 ns` (🚀 **11.00x faster**) |
| | `Ethers` | `Alloy` |
| :-------------- | :------------------------- | :-------------------------------- |
| **`amountIn`** | `512.47 ns` (✅ **1.00x**) | `216.32 ns` (🚀 **2.37x faster**) |
| **`amountOut`** | `53.82 ns` (✅ **1.00x**) | `18.19 ns` (🚀 **2.96x faster**) |

## U256 Operations
## Rlp Encoding and Decoding

For this benchmark, we are computing the `amountIn` and `amountOut` for the [`swap` function call](https://github.com/Uniswap/v2-core/blob/ee547b17853e71ed4e0101ccfd52e70d5acded58/contracts/UniswapV2Pair.sol#L159) from the current reserves of the Uniswap V2 pair, demonstrating the use of `U256` operations.
Rlp encoding and decoding comparison against [Parity tech rlp](https://crates.io/crates/rlp).
For this benchmark, we shall derive the `Encodable` and `Decodable` traits for a simple struct:

```rust
#[derive(alloy_rlp::RlpEncodable, alloy_rlp::RlpDecodable, rlp_derive::RlpDecodable,rlp_derive::RlpEncodable)]
pub struct MyStruct {
pub a: u128,
pub b: Vec<u8>,
}
```

| | `Parity-Rlp` | `Alloy-Rlp` |
| :------------- | :------------------------ | :------------------------------- |
| **`Encoding`** | `86.70 ns` (✅ **1.00x**) | `26.88 ns` (🚀 **3.23x faster**) |
| **`Decoding`** | `88.79 ns` (✅ **1.00x**) | `21.43 ns` (🚀 **4.14x faster**) |

## JSON-ABI

For this benchmark we shall compare ABI serialize and deserialize performance against [ethabi](https://crates.io/crates/ethabi) for widely used contracts such as [Seaport](https://etherscan.io/address/0x00000000000000adc04c56bf30ac9d3c0aaf14dc), [Uniswap V4 Pool Manager](https://etherscan.io/address/0x000000000004444c5dc75cB358380D2e3dE08A90) and [Uniswap V3 Pool](https://etherscan.io/address/0x99ac8cA7087fA4A2A1FB6357269965A2014ABc35).

### Serialization

| | `EthAbi` | `Alloy` |
| :------------------ | :------------------------ | :------------------------------- |
| **`Seaport`** | `35.43 us` (✅ **1.00x**) | `38.68 us` (✅ **1.09x slower**) |
| **`PoolManager`** | `18.33 us` (✅ **1.00x**) | `17.94 us` (✅ **1.02x faster**) |
| **`UniswapV3Pool`** | `14.61 us` (✅ **1.00x**) | `12.99 us` (✅ **1.12x faster**) |

### Deserialization

### UNIV2: Get Amount In
| | `EthAbi` | `Alloy` |
| :------------------ | :------------------------- | :-------------------------------- |
| **`Seaport`** | `209.43 us` (✅ **1.00x**) | `210.67 us` (✅ **1.01x slower**) |
| **`PoolManager`** | `89.05 us` (✅ **1.00x**) | `93.31 us` (✅ **1.05x slower**) |
| **`UniswapV3Pool`** | `63.24 us` (✅ **1.00x**) | `68.50 us` (✅ **1.08x slower**) |

| | `Ethers` | `Alloy` |
| :-- | :------------------------- | :-------------------------------- |
| | `503.52 ns` (✅ **1.00x**) | `245.98 ns` (🚀 **2.05x faster**) |
## Serialize/Deserialize Function Signature

### UNIV2: Get Amount Out
For this benchmark, we'll compare the serde performance of a large function signature.

| | `Ethers` | `Alloy` |
| :-- | :------------------------ | :------------------------------- |
| | `53.75 ns` (✅ **1.00x**) | `18.22 ns` (🚀 **2.95x faster**) |
| | `EthAbi` | `Alloy` |
| :---------------- | :------------------------ | :--------------------------------- |
| **`Serialize`** | `5.03 us` (✅ **1.00x**) | `247.82 ns` (🚀 **20.29x faster**) |
| **`Deserialize`** | `14.10 us` (✅ **1.00x**) | `14.05 us` (✅ **1.00x faster**) |
1 change: 1 addition & 0 deletions benches/artifacts/LargeFunction.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"type":"function","name":"fulfillAvailableAdvancedOrders","inputs":[{"name":"","type":"tuple[]","internalType":"struct AdvancedOrder[]","components":[{"name":"parameters","type":"tuple","internalType":"struct OrderParameters","components":[{"name":"offerer","type":"address","internalType":"address"},{"name":"zone","type":"address","internalType":"address"},{"name":"offer","type":"tuple[]","internalType":"struct OfferItem[]","components":[{"name":"itemType","type":"uint8","internalType":"enum ItemType"},{"name":"token","type":"address","internalType":"address"},{"name":"identifierOrCriteria","type":"uint256","internalType":"uint256"},{"name":"startAmount","type":"uint256","internalType":"uint256"},{"name":"endAmount","type":"uint256","internalType":"uint256"}]},{"name":"consideration","type":"tuple[]","internalType":"struct ConsiderationItem[]","components":[{"name":"itemType","type":"uint8","internalType":"enum ItemType"},{"name":"token","type":"address","internalType":"address"},{"name":"identifierOrCriteria","type":"uint256","internalType":"uint256"},{"name":"startAmount","type":"uint256","internalType":"uint256"},{"name":"endAmount","type":"uint256","internalType":"uint256"},{"name":"recipient","type":"address","internalType":"address payable"}]},{"name":"orderType","type":"uint8","internalType":"enum OrderType"},{"name":"startTime","type":"uint256","internalType":"uint256"},{"name":"endTime","type":"uint256","internalType":"uint256"},{"name":"zoneHash","type":"bytes32","internalType":"bytes32"},{"name":"salt","type":"uint256","internalType":"uint256"},{"name":"conduitKey","type":"bytes32","internalType":"bytes32"},{"name":"totalOriginalConsiderationItems","type":"uint256","internalType":"uint256"}]},{"name":"numerator","type":"uint120","internalType":"uint120"},{"name":"denominator","type":"uint120","internalType":"uint120"},{"name":"signature","type":"bytes","internalType":"bytes"},{"name":"extraData","type":"bytes","internalType":"bytes"}]},{"name":"","type":"tuple[]","internalType":"struct CriteriaResolver[]","components":[{"name":"orderIndex","type":"uint256","internalType":"uint256"},{"name":"side","type":"uint8","internalType":"enum Side"},{"name":"index","type":"uint256","internalType":"uint256"},{"name":"identifier","type":"uint256","internalType":"uint256"},{"name":"criteriaProof","type":"bytes32[]","internalType":"bytes32[]"}]},{"name":"","type":"tuple[][]","internalType":"struct FulfillmentComponent[][]","components":[{"name":"orderIndex","type":"uint256","internalType":"uint256"},{"name":"itemIndex","type":"uint256","internalType":"uint256"}]},{"name":"","type":"tuple[][]","internalType":"struct FulfillmentComponent[][]","components":[{"name":"orderIndex","type":"uint256","internalType":"uint256"},{"name":"itemIndex","type":"uint256","internalType":"uint256"}]},{"name":"fulfillerConduitKey","type":"bytes32","internalType":"bytes32"},{"name":"recipient","type":"address","internalType":"address"},{"name":"maximumFulfilled","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool[]","internalType":"bool[]"},{"name":"","type":"tuple[]","internalType":"struct Execution[]","components":[{"name":"item","type":"tuple","internalType":"struct ReceivedItem","components":[{"name":"itemType","type":"uint8","internalType":"enum ItemType"},{"name":"token","type":"address","internalType":"address"},{"name":"identifier","type":"uint256","internalType":"uint256"},{"name":"amount","type":"uint256","internalType":"uint256"},{"name":"recipient","type":"address","internalType":"address payable"}]},{"name":"offerer","type":"address","internalType":"address"},{"name":"conduitKey","type":"bytes32","internalType":"bytes32"}]}],"stateMutability":"payable"}
1 change: 1 addition & 0 deletions benches/artifacts/Seaport.json

Large diffs are not rendered by default.

Loading
Loading