-
Notifications
You must be signed in to change notification settings - Fork 43
Metrics and load testing #121
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
Changes from 35 commits
c90177c
9ac2960
59e7931
3ba620d
a262b34
cdad812
9f65698
1f9fe4d
ae9641f
8272ed9
e78c225
56ef9a0
d254ec2
b5b4502
15cada8
f0cc6a9
4d74529
d7b82a2
6541a73
8ec09b6
d34f5b5
126e4e5
3a9cf7b
b87f88d
1a23736
c2bc241
55da6cf
4d58ead
20a3d9b
03618d6
59485ab
14cdfe0
f5a389d
35e13f1
79bc854
069a696
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| # TIPS Load Testing | ||
|
|
||
| Multi-wallet concurrent load testing tool for measuring TIPS performance. | ||
|
|
||
| ## Quick Start | ||
|
|
||
| ```bash | ||
| # 1. Build | ||
| cargo build --release --bin load-test | ||
|
|
||
| # 2. Setup wallets | ||
| ./target/release/load-test setup \ | ||
| --master-key 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d \ | ||
| --output wallets.json | ||
|
|
||
| # 3. Run load test | ||
| ./target/release/load-test load --wallets wallets.json | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Configuration Options | ||
|
|
||
| ### Setup Command | ||
|
|
||
| Create and fund test wallets from a master wallet. Test wallets are saved to allow test reproducibility and avoid the need to create new wallets for every test run. | ||
|
|
||
| **Usage:** | ||
| ```bash | ||
| load-test setup --master-key <KEY> --output <FILE> [OPTIONS] | ||
| ``` | ||
|
|
||
| **Options:** | ||
|
|
||
| | Flag | Description | Default | Example | | ||
| |------|-------------|---------|---------| | ||
| | `--master-key` | Private key of funded wallet (required) | - | `0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d` | | ||
| | `--output` | Save wallets to JSON file (required) | - | `wallets.json` | | ||
| | `--sequencer` | L2 sequencer RPC URL | `http://localhost:8547` | `http://localhost:8547` | | ||
| | `--num-wallets` | Number of wallets to create | `10` | `100` | | ||
| | `--fund-amount` | ETH to fund each wallet | `0.1` | `0.5` | | ||
|
|
||
| **Environment Variables:** | ||
| - `MASTER_KEY` - Alternative to `--master-key` flag | ||
| - `SEQUENCER_URL` - Alternative to `--sequencer` flag | ||
|
|
||
| ### Load Command | ||
|
|
||
| Run load test with funded wallets. Use the `--seed` flag to set the RNG seed for test reproducibility. | ||
|
|
||
| **Usage:** | ||
| ```bash | ||
| load-test load --wallets <FILE> [OPTIONS] | ||
|
||
| ``` | ||
|
|
||
| **Options:** | ||
|
|
||
| | Flag | Description | Default | Example | | ||
| |------|-------------|---------|---------| | ||
| | `--wallets` | Path to wallets JSON file (required) | - | `wallets.json` | | ||
| | `--target` | TIPS ingress RPC URL | `http://localhost:8080` | `http://localhost:8080` | | ||
| | `--sequencer` | L2 sequencer RPC URL | `http://localhost:8547` | `http://localhost:8547` | | ||
| | `--rate` | Target transaction rate (tx/s) | `100` | `500` | | ||
| | `--duration` | Test duration in seconds | `60` | `100` | | ||
| | `--tx-timeout` | Timeout for tx inclusion (seconds) | `60` | `120` | | ||
| | `--seed` | Random seed for reproducibility | (none) | `42` | | ||
| | `--output` | Save metrics to JSON file | (none) | `metrics.json` | | ||
|
|
||
| **Environment Variables:** | ||
| - `INGRESS_URL` - Alternative to `--target` flag | ||
| - `SEQUENCER_URL` - Alternative to `--sequencer` flag | ||
|
|
||
| --- | ||
| --- | ||
|
|
||
| ## Metrics Explained | ||
|
|
||
| ### Output Example | ||
|
|
||
| ``` | ||
| Load Test Results | ||
| ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ | ||
| Configuration: | ||
| Target: http://localhost:8080 | ||
| Sequencer: http://localhost:8547 | ||
| Wallets: 100 | ||
| Target Rate: 100 tx/s | ||
|
Comment on lines
+86
to
+87
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. qq: is it correct to assume that the target TPS is evenly distributed across the number of wallets?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exactly. Could make this configurable as well if needed |
||
| Duration: 60s | ||
| TX Timeout: 60s | ||
|
|
||
| Throughput: | ||
| Sent: 100.0 tx/s (6000 total) | ||
| Included: 98.5 tx/s (5910 total) | ||
| Success Rate: 98.5% | ||
|
|
||
| Transaction Results: | ||
| Included: 5910 (98.5%) | ||
| Reverted: 10 (0.2%) | ||
| Timed Out: 70 (1.2%) | ||
| Send Errors: 10 (0.1%) | ||
| ``` | ||
|
|
||
| ### Metrics Definitions | ||
|
|
||
| **Throughput:** | ||
| - `Sent Rate` - Transactions sent to TIPS per second | ||
| - `Included Rate` - Transactions included in blocks per second | ||
| - `Success Rate` - Percentage of sent transactions that were included | ||
|
|
||
| **Transaction Results:** | ||
| - `Included` - Successfully included in a block with status == true | ||
| - `Reverted` - Included in a block but transaction reverted (status == false) | ||
| - `Timed Out` - Not included within timeout period | ||
| - `Send Errors` - Failed to send to TIPS RPC | ||
|
|
||
| --- | ||
|
|
||
| ## Architecture | ||
|
|
||
| ``` | ||
| Sender Tasks (1 per wallet) Receipt Poller | ||
| │ │ | ||
| ▼ ▼ | ||
| Send to TIPS ──► Tracker ◄── Poll sequencer every 2s | ||
| (retry 3x) (pending) │ | ||
| │ │ ├─ status=true → included | ||
| │ │ ├─ status=false → reverted | ||
| │ │ └─ timeout → timed_out | ||
| ▼ ▼ | ||
| rate/N tx/s Calculate Results → Print Summary | ||
| ``` | ||
|
|
||
| --- | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| use anyhow::Result; | ||
| use clap::Parser; | ||
| use tips_system_tests::load_test::{config, load, setup}; | ||
|
|
||
| #[tokio::main] | ||
| async fn main() -> Result<()> { | ||
| let cli = config::Cli::parse(); | ||
|
|
||
| match cli.command { | ||
| config::Commands::Setup(args) => setup::run(args).await, | ||
| config::Commands::Load(args) => load::run(args).await, | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| pub mod client; | ||
| pub mod fixtures; | ||
| pub mod load_test; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| use clap::{Parser, Subcommand}; | ||
| use std::path::PathBuf; | ||
|
|
||
| #[derive(Parser)] | ||
| #[command(name = "load-test")] | ||
| #[command(about = "Load testing tool for TIPS ingress service", long_about = None)] | ||
| pub struct Cli { | ||
| #[command(subcommand)] | ||
| pub command: Commands, | ||
| } | ||
|
|
||
| #[derive(Subcommand)] | ||
| pub enum Commands { | ||
| /// Setup: Fund N wallets from a master wallet | ||
| Setup(SetupArgs), | ||
| /// Load: Run load test with funded wallets | ||
| Load(LoadArgs), | ||
| } | ||
|
|
||
| #[derive(Parser)] | ||
| pub struct SetupArgs { | ||
| /// Master wallet private key (must have funds) | ||
| #[arg(long, env = "MASTER_KEY")] | ||
| pub master_key: String, | ||
|
|
||
| /// Sequencer RPC URL | ||
| #[arg(long, env = "SEQUENCER_URL", default_value = "http://localhost:8547")] | ||
| pub sequencer: String, | ||
|
|
||
| /// Number of wallets to create and fund | ||
| #[arg(long, default_value = "10")] | ||
| pub num_wallets: usize, | ||
|
|
||
| /// Amount of ETH to fund each wallet | ||
| #[arg(long, default_value = "0.1")] | ||
| pub fund_amount: f64, | ||
|
|
||
| /// Output file for wallet data (required) | ||
| #[arg(long)] | ||
| pub output: PathBuf, | ||
| } | ||
|
|
||
| #[derive(Parser)] | ||
| pub struct LoadArgs { | ||
| /// TIPS ingress RPC URL | ||
| #[arg(long, env = "INGRESS_URL", default_value = "http://localhost:8080")] | ||
| pub target: String, | ||
|
|
||
| /// Sequencer RPC URL (for nonce fetching and receipt polling) | ||
| #[arg(long, env = "SEQUENCER_URL", default_value = "http://localhost:8547")] | ||
| pub sequencer: String, | ||
|
|
||
| /// Path to wallets JSON file (required) | ||
| #[arg(long)] | ||
| pub wallets: PathBuf, | ||
|
|
||
| /// Target transaction rate (transactions per second) | ||
| #[arg(long, default_value = "100")] | ||
| pub rate: u64, | ||
|
|
||
| /// Test duration in seconds | ||
| #[arg(long, default_value = "60")] | ||
| pub duration: u64, | ||
|
|
||
| /// Timeout for transaction inclusion (seconds) | ||
| #[arg(long, default_value = "60")] | ||
| pub tx_timeout: u64, | ||
|
|
||
| /// Random seed for reproducibility | ||
| #[arg(long)] | ||
| pub seed: Option<u64>, | ||
|
|
||
| /// Output file for metrics (JSON) | ||
| #[arg(long)] | ||
| pub output: Option<PathBuf>, | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be
./target/release/load-test?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yep, good catch!