# grpcpulse
A CLI tool and Rust library to benchmark and compare gRPC endpoints side by side.
Measures latency, throughput, and stream lag — built for comparing Solana RPC providers
(Shyft, Helius, Triton) or any gRPC service.
## Install
```bash
cargo install grpcpulse
```
## Modes
### Latency — round-trip benchmark
Fires N concurrent requests and reports p50/p95/p99 latency per endpoint:
```bash
grpcpulse latency \
--requests 100 \
--concurrency 10 \
--warmup 5
```
```
+----------+---------+---------+---------+---------+--------+
| my-node | 4.12ms | 8.34ms | 12.01ms | 25.40ms | 0.0% |
| shyft | 93.10ms | 127ms | 128ms | 128ms | 0.0% |
+----------+---------+---------+---------+---------+--------+
```
### Stream — Solana slot lag comparison
Subscribes to Geyser slot streams on all endpoints simultaneously and measures
which provider delivers each slot first:
```bash
grpcpulse stream \
--slots 50
```
```
+-----------+------+-------+--------------+------------+
| shyft-ams | 36 | 69.2% | 16.53 | 52 |
| shyft-sgp | 16 | 30.8% | 2.38 | 52 |
+-----------+------+-------+--------------+------------+
Fastest: shyft-ams (36/50 slots, avg 0.00ms ahead)
```
## Auth headers
Pass headers per endpoint using `|key:value` after the URL:
```bash
Or globally with `-H` (applies to all endpoints):
```bash
-H "authorization:Bearer mytoken"
```
## Use as a library
```rust
use grpcpulse::bench::{run, BenchConfig};
use grpcpulse::endpoint::Endpoint;
use grpcpulse::report::print_table;
#[tokio::main]
async fn main() {
let endpoints = vec![
Endpoint::new("shyft", "https://grpc.shyft.to")
.with_header("x-token", "YOUR_TOKEN"),
Endpoint::new("local", "http://localhost:10000"),
];
let results = run(endpoints, BenchConfig::default()).await;
print_table(&results);
}
```
## Options
### `grpcpulse latency`
| `--endpoint` | `name=url` or `name=url\|key:value` | required |
| `-H` | Global header `key:value` | — |
| `--requests` | Requests per endpoint | 100 |
| `--concurrency` | Parallel requests per batch | 10 |
| `--warmup` | Warmup requests (results discarded) | 5 |
### `grpcpulse stream`
| `--endpoint` | `name=url` or `name=url\|key:value` | required |
| `-H` | Global header `key:value` | — |
| `--slots` | Number of slots to collect | 50 |
## License
MIT