Skip to content
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

feat(core): add I/O heavy load test #2090

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
20 changes: 9 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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 loc-detailed \
loc-compare-detailed
loc-compare-detailed load-test-fibonacci load-test-io

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}'
Expand Down Expand Up @@ -193,16 +193,14 @@ start-node-with-flamegraph: rm-test-db ## 🚀🔥 Starts an ethrex client used
--dev \
--datadir test_ethrex

load-node: install-cli ## 🚧 Runs a load-test. Run make start-node-with-flamegraph and in a new terminal make load-node
@if [ -z "$$C" ]; then \
CONTRACT_INTERACTION=""; \
echo "Running the load-test without contract interaction"; \
echo "If you want to interact with contracts to load the evm, run the target with a C at the end: make <target> C=1"; \
else \
CONTRACT_INTERACTION="-c"; \
echo "Running the load-test with contract interaction"; \
fi; \
ethrex_l2 test load --path test_data/private_keys.txt -i 1000 -v --value 100000 $$CONTRACT_INTERACTION
load-test: install-cli ## 🚧 Runs a load-test. Run make start-node-with-flamegraph and in a new terminal make load-node
ethrex_l2 test load --path test_data/private_keys.txt -i 1000 -v --value 100000

load-test-fibonacci:
ethrex_l2 test load --path test_data/private_keys.txt -i 1000 -v --value 100000 --fibonacci

load-test-io:
ethrex_l2 test load --path test_data/private_keys.txt -i 1000 -v --value 100000 --io

rm-test-db: ## 🛑 Removes the DB used by the ethrex client used for testing
sudo cargo run --release --bin ethrex -- removedb --datadir test_ethrex
Expand Down
34 changes: 27 additions & 7 deletions cmd/ethrex_l2/src/commands/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,13 @@ pub(crate) enum Command {
)]
verbose: bool,
#[clap(
short = 'c',
long = "contract",
long = "fibonacci",
default_value = "false",
help = "send value to address with contract"
help = "Run fibonacci load test"
)]
contract: bool,
fibonacci: bool,
#[clap(long = "io", default_value = "false", help = "Run I/O-heavy load test")]
i_o_heavy: bool,
},
}

Expand Down Expand Up @@ -116,7 +117,7 @@ async fn transfer_from(
},
max_fee_per_gas: Some(3121115334),
max_priority_fee_per_gas: Some(3000000000),
gas_limit: Some(TX_GAS_COST * 5),
gas_limit: Some(TX_GAS_COST * 100),
..Default::default()
},
10,
Expand Down Expand Up @@ -163,7 +164,8 @@ impl Command {
value,
iterations,
verbose,
contract,
fibonacci,
i_o_heavy,
} => {
let Ok(lines) = read_lines(path) else {
return Ok(());
Expand All @@ -178,7 +180,7 @@ impl Command {
None => Address::random(),
};

let calldata: Bytes = if contract {
let calldata: Bytes = if fibonacci {
// This is the bytecode for the contract with the following functions
// version() -> always returns 2
// function fibonacci(uint n) public pure returns (uint) -> returns the nth fib number
Expand All @@ -201,6 +203,24 @@ impl Command {
&[Value::Uint(100000000000000_u64.into())],
)?
.into()
} else if i_o_heavy {
// Contract with a function that touches 100 storage slots on every transaction.
// See `test_data/IOHeavyContract.sol` for the code.
let init_code = hex::decode("6080604052348015600e575f5ffd5b505f5f90505b6064811015603e57805f8260648110602d57602c6043565b5b018190555080806001019150506014565b506070565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b6102728061007d5f395ff3fe608060405234801561000f575f5ffd5b506004361061003f575f3560e01c8063431aabc21461004357806358faa02f1461007357806362f8e72a1461007d575b5f5ffd5b61005d6004803603810190610058919061015c565b61009b565b60405161006a9190610196565b60405180910390f35b61007b6100b3565b005b61008561010a565b6040516100929190610196565b60405180910390f35b5f81606481106100a9575f80fd5b015f915090505481565b5f5f90505b60648110156101075760015f82606481106100d6576100d56101af565b5b01546100e29190610209565b5f82606481106100f5576100f46101af565b5b018190555080806001019150506100b8565b50565b5f5f5f6064811061011e5761011d6101af565b5b0154905090565b5f5ffd5b5f819050919050565b61013b81610129565b8114610145575f5ffd5b50565b5f8135905061015681610132565b92915050565b5f6020828403121561017157610170610125565b5b5f61017e84828501610148565b91505092915050565b61019081610129565b82525050565b5f6020820190506101a95f830184610187565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61021382610129565b915061021e83610129565b9250828201905080821115610236576102356101dc565b5b9291505056fea264697066735822122055f6d7149afdb56c745a203d432710eaa25a8ccdb030503fb970bf1c964ac03264736f6c634300081b0033")?;
let client = EthClient::new(&cfg.network.l2_rpc_url);

let (_, contract_address) = client
.deploy(
cfg.wallet.address,
cfg.wallet.private_key,
init_code.into(),
Overrides::default(),
)
.await?;

to_address = contract_address;

calldata::encode_calldata("incrementNumbers()", &[])?.into()
} else {
Bytes::new()
};
Expand Down
20 changes: 19 additions & 1 deletion crates/l2/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,25 @@ Configuration is done through env vars. A detailed list is available in each par

## Testing

Load tests are available via L2 CLI. The test take a list of private keys and send a bunch of transactions from each of them to some address.
Load tests are available via L2 CLI and Makefile targets.

### Makefile

There are currently three different load tests you can run:

```
make load-test
make load-test-fibonacci
make load-test-io
```

The first one sends regular transfers between accounts, the second runs an EVM-heavy contract that computes fibonacci numbers, the third a heavy IO contract that writes to 100 storage slots per transaction.

### CLI

To have more control over the load tests and its parameters, you can use the CLI (the Makefile targets use the CLI underneath).

The tests take a list of private keys and send a bunch of transactions from each of them to some address (either the address of some account to send eth to or the address of the contract that we're interacting with).

The CLI can be installed with the `cli` target:

Expand Down
25 changes: 25 additions & 0 deletions test_data/load_test/IOHeavyContract.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

// Contract used in the `load-test-io` Makefile target. The test sends transactions calling
// the `incrementNumbers()` function, which writes to 100 storage slots.

contract Counter {
uint256[100] public number;

constructor() {
for(uint i = 0; i < 100; i++) {
number[i] = i;
}
}

function incrementNumbers() public {
for(uint i = 0; i < 100; i++) {
number[i] = number[i] + 1;
}
}

function getFirstNumber() public view returns(uint256) {
return number[0];
}
}