Skip to content
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
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ python3 -m chainbench start --profile bsc --users 50 --workers 2 --test-time 12h
````

### Parameters and Flags
- `--profile`: This flag specifies the profile to use for the benchmark. Available profiles are `ethereum`, `bsc`, `polygon` and `avalanche`.
- `--profile`: This flag specifies the profile to use for the benchmark. Available profiles are `ethereum`, `bsc`, `polygon`, `oasis`, and `avalanche`.
- `--users`: This flag sets the number of simulated users to use for the benchmark.
- `--workers`: This flag sets the number of worker threads to use for the benchmark.
- `--test-time`: This flag sets the duration of the test to run.
Expand All @@ -58,4 +58,8 @@ If you want to run a load test for BSC in headless mode, run the following comma
python3 -m chainbench start --profile bsc --workers 4 --users 100 --test-time 1h --target https://node-url --headless --autoquit
```

It will run a load test for BSC with 4 workers, 100 users and 1 hour test time.
It will run a load test for BSC with 4 workers, 100 users and 1 hour test time.

## Custom Profiles

For a tutorial on how to create custom profiles, please refer to [this document](docs/PROFILE.md).
38 changes: 21 additions & 17 deletions chainbench/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,48 +20,52 @@
MASTER_PORT = "5557"
WORKER_COUNT = 16
TEST_TIME = "1h"
USERS = 10000
USERS = 1000
SPAWN_RATE = 10
LOG_LEVEL = "DEBUG"
DEFAULT_PROFILE = "ethereum"
PROFILES = [
"avalanche",
"bsc",
"ethereum",
"polygon",
]
NOTIFY_URL_TEMPLATE = "https://ntfy.sh/{topic}"

logger = logging.getLogger(__name__)


@click.group(
help="Locust CLI",
help="Tool for flexible blockchain infrastructure benchmarking.",
)
@click.pass_context
def cli(ctx: click.Context):
ctx.obj = ContextData()


@cli.command()
@cli.command(
help="Start the test using the configured profile. "
"By default, the results are saved in the "
"./results/{profile}/{YYYY-mm-dd_HH-MM-SS} directory.",
)
@click.option(
"--profile",
default=DEFAULT_PROFILE,
type=click.Choice(PROFILES, case_sensitive=False),
help="Profile to run",
show_default=True,
)
@click.option("--host", default=MASTER_HOST, help="Host to run on", show_default=True)
@click.option("--port", default=MASTER_PORT, help="Port to run on", show_default=True)
@click.option(
"--workers",
default=WORKER_COUNT,
help="Number of workers to run",
show_default=True,
)
@click.option("--host", default=MASTER_HOST, help="Host to run")
@click.option("--port", default=MASTER_PORT, help="Port to run")
@click.option("--workers", default=WORKER_COUNT, help="Number of workers to run")
@click.option("--test-time", default=TEST_TIME, help="Test time in seconds")
@click.option("--users", default=USERS, help="Number of users")
@click.option("--spawn-rate", default=SPAWN_RATE, help="Spawn rate")
@click.option("--log-level", default=LOG_LEVEL, help="Log level")
@click.option("--test-time", default=TEST_TIME, help="Test time", show_default=True)
@click.option("--users", default=USERS, help="Number of users", show_default=True)
@click.option("--spawn-rate", default=SPAWN_RATE, help="Spawn rate", show_default=True)
@click.option("--log-level", default=LOG_LEVEL, help="Log level", show_default=True)
@click.option(
"--results-dir",
default=Path("results"),
help="Results directory",
type=click.Path(),
show_default=True,
)
@click.option("--headless", is_flag=True, help="Run in headless mode")
@click.option("--autoquit", is_flag=True, help="Auto quit after test")
Expand Down
2 changes: 1 addition & 1 deletion chainbench/profile/avalanche.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def get_balance_task(self):
self.make_call(
name="get_balance",
method="eth_getBalance",
params=self._get_balance_params_factory(),
params=self._get_balance_params_factory_latest(),
),

@task(10)
Expand Down
2 changes: 1 addition & 1 deletion chainbench/profile/bsc.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def get_balance_task(self):
self.make_call(
name="get_balance",
method="eth_getBalance",
params=self._get_balance_params_factory(),
params=self._get_balance_params_factory_latest(),
),

@task(3)
Expand Down
2 changes: 1 addition & 1 deletion chainbench/profile/ethereum.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def get_balance_task(self):
self.make_call(
name="get_balance",
method="eth_getBalance",
params=self._get_balance_params_factory(),
params=self._get_balance_params_factory_latest(),
),

@task(11)
Expand Down
68 changes: 68 additions & 0 deletions chainbench/profile/oasis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from chainbench.user.evm import EVMBenchUser
from locust import task, between


class OasisProfile(EVMBenchUser):
wait_time = between(0.1, 1.5)

@task
def get_block_by_number_task(self):
self.make_call(
name="get_block_by_number",
method="eth_getBlockByNumber",
params=self._block_by_number_params_factory(),
),

@task
def get_balance_task(self):
self.make_call(
name="get_balance",
method="eth_getBalance",
params=self._get_balance_params_factory(),
),

@task
def get_transaction_count_task(self):
self.make_call(
name="get_transaction_count",
method="eth_getTransactionCount",
params=self._get_balance_params_factory(),
),

@task
def get_code_task(self):
self.make_call(
name="get_code",
method="eth_getCode",
params=self._get_balance_params_factory(),
),

@task
def get_transaction_by_hash_task(self):
self.make_call(
name="get_transaction_by_hash",
method="eth_getTransactionByHash",
params=self._transaction_by_hash_params_factory(),
),

@task
def get_block_number_task(self):
self.make_call(
name="block_number",
method="eth_blockNumber",
),

@task
def get_syncing_task(self):
self.make_call(
name="get_syncing",
method="eth_syncing",
),

@task
def get_block_transaction_count_by_number_task(self):
self.make_call(
name="get_block_transaction_count_by_number",
method="eth_getBlockTransactionCountByNumber",
params=self._random_block_number_params_factory(),
),
2 changes: 1 addition & 1 deletion chainbench/profile/polygon.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def get_balance_task(self):
self.make_call(
name="get_balance",
method="eth_getBalance",
params=self._get_balance_params_factory(),
params=self._get_balance_params_factory_latest(),
),

# TODO: introduce tags to make it possible to filter out unsupported methods
Expand Down
11 changes: 10 additions & 1 deletion chainbench/user/evm.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,20 @@ def _get_logs_params_factory(self):
def _transaction_by_hash_params_factory(self):
return [self.test_data.get_random_tx_hash()]

def _random_block_number_params_factory(self):
return [self.test_data.get_random_block_number_hex()]

def _block_by_number_params_factory(self):
return [self.test_data.get_random_block_number_hex(), random_bool()]

def _block_by_hash_params_factory(self):
return [self.test_data.get_random_block_hash(), random_bool()]

def _get_balance_params_factory(self):
def _get_balance_params_factory_latest(self):
return [self.test_data.get_random_account(), "latest"]

def _get_balance_params_factory(self):
return [
self.test_data.get_random_account(),
self.test_data.get_random_block_number_hex(),
]
Loading