Metadata-Version: 2.4
Name: rpcbench
Version: 0.1.1
Summary: Compare EVM JSON-RPC endpoints: latency, percentiles, errors, ranked CLI and JSON.
Author: Ehsan Hajian
License-Expression: MIT
Project-URL: Homepage, https://github.com/ehsanhajian/RPCBench
Project-URL: Repository, https://github.com/ehsanhajian/RPCBench
Project-URL: Issues, https://github.com/ehsanhajian/RPCBench/issues
Keywords: rpc,ethereum,json-rpc,benchmark,latency
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: System :: Benchmark
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.27
Requires-Dist: PyYAML>=6.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Dynamic: license-file

# RPCBench

**Which RPC endpoint is fastest — for this call, from this machine?**

A small CLI that compares **EVM JSON-RPC over HTTP**: latency, P50/P95/P99, error rate, a ranked table, and JSON. Read-only by default. No accounts. No telemetry. Localhost and RFC1918 are allowed (that is how you bench your own node).

It is **not** a security scanner ([Nodeprobe](https://github.com/ehsanhajian/nodeprobe)) and **not** validator monitoring ([ValidatorPulse](https://github.com/ehsanhajian/ValidatorPulse)). Split: [docs/BOUNDARY.md](https://github.com/ehsanhajian/RPCBench/blob/main/docs/BOUNDARY.md). Roadmap: [issues](https://github.com/ehsanhajian/RPCBench/issues) · epic [#19](https://github.com/ehsanhajian/RPCBench/issues/19).

## Install

```bash
pip install rpcbench
```

Python 3.10+. `rpcbench --version` prints `0.1.1`.

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
```

PRs run `pytest`, then a live smoke against PublicNode and dRPC (`--samples 1 --warmup 0`). No local node in CI; the smoke passes if either public endpoint is ok.

## Quick start

```bash
rpcbench compare --endpoints https://ethereum.publicnode.com --samples 5 --warmup 1
```

Or a YAML/JSON file of named endpoints (keep API keys in a **local** file; do not commit it):

```yaml
endpoints:
  - name: publicnode
    url: https://ethereum.publicnode.com
  - name: drpc
    url: https://eth.drpc.org
  - name: paid
    url: https://eth.example/v3/YOUR_KEY
    bearer: YOUR_TOKEN
    headers:
      X-Api-Key: YOUR_KEY
```

```bash
rpcbench run --endpoints endpoints.yaml
rpcbench compare --endpoints endpoints.yaml --json
rpcbench run --endpoints endpoints.yaml -o report.json
```

`run` and `compare` are the same command.

## Report

The CLI prints, in order:

1. **Summary** — Fastest (P95 by default)
2. **Comparison** — same numbers in **your YAML order** (failed rows stay in place)
3. **Ranking** — ordered by `--rank-by`; failed endpoints last, never Fastest
4. **Providers** — redacted URL + `id=` hash, samples, errors
5. **Capabilities** — who answered this method

On a TTY, ok is green and fail is red (`NO_COLOR` or a pipe turns color off). Reports never print API keys, bearer tokens, or header values.

## How a run works

- **Paired by default:** one shared read-only sequence; each sample is raced to every provider at the same time. `--sequential` is A-then-B.
- **Warmup is excluded** from min/mean/max, percentiles, and error rate.
- **P50/P95/P99** are nearest-rank over successful samples.
- **Error rate** is failed/attempted, with a class (timeout, connection, HTTP 4xx/5xx, JSON-RPC, malformed).
- **Ranking** is P95 of successes. Override with `--rank-by p50|p95|p99|mean|rps` (`throughput` = `rps`). Lower latency wins; higher rps wins. Ties: mean, then config order.
- **rps** is `1000 / mean_ms` for this probe — not parallel throughput.
- **JSON** (`--json` or `-o FILE`) includes `mode`, `seed`, `sequence_id`, and per-sample `pairs` (body hashes). Reliability `score` is success rate.

## Flags

```bash
rpcbench run --endpoints endpoints.yaml --samples 10 --warmup 1 --preset head
rpcbench compare --endpoints http://127.0.0.1:8545
rpcbench run --endpoints endpoints.yaml --rank-by p95
rpcbench run --endpoints endpoints.yaml --sequential
rpcbench run --endpoints endpoints.yaml --verbose --json
```

| Flag | Default | |
| --- | --- | --- |
| `--samples` | 10 | Timed requests per endpoint after warmup |
| `--warmup` | 1 | Requests excluded from stats |
| `--timeout` | 10s | Per-request timeout |
| `--budget` | 128 | Max HTTP requests for the whole run (hard cap `RPCBENCH_MAX_REQUESTS`, default 10000) |
| `--max-duration` | 600s | Stop remaining work and still print a report (`0` = no limit) |
| `--concurrency` | 0 | Paired-wave cap (`0` = all providers). Not a load burst |
| `--seed` | 0 | Shared sequence stamp |
| `--rank-by` | `p95` | `p50`, `p95`, `p99`, `mean`, or `rps` |
| `--preset` | | `head` (`eth_blockNumber`), `chainId`, or `balance` (`eth_getBalance` of the zero address) |
| `--method` / `--params` | `eth_blockNumber` | JSON-RPC method and JSON array of params. Do not combine `--method` with `--preset` |
| `--allow-writes` | off | Required for write methods (`eth_send*`, `personal_*`, …) |
| `--verbose` | off | Print each sample |
| `--json` / `-o FILE` | | JSON to stdout, and/or write JSON to a file (table still prints unless `--json`) |
| `--sequential` | off | Run endpoints back-to-back instead of paired |

## Safety

Kill switch: `RPCBENCH_DISABLED=1`, or create `~/.config/rpcbench/DISABLED` (override path with `RPCBENCH_DISABLE_FILE`). RPCBench never prompts for a private key.

## License

[MIT](https://github.com/ehsanhajian/RPCBench/blob/main/LICENSE)
