Skip to content

Commit bc5f66d

Browse files
committed
feat: commit (updated) rpc benchmark
1 parent fefd510 commit bc5f66d

10 files changed

Lines changed: 3489 additions & 0 deletions

File tree

examples/rpc-benchmark/README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# RPC Benchmark
2+
3+
Stress test for LiveKit RPC with configurable payload sizes. Exercises all three RPC transport paths:
4+
5+
| Path | Payload Size | Description |
6+
|------|-------------|-------------|
7+
| Legacy | < 1 KB | Uncompressed inline payload |
8+
| Compressed | 1 KB – 15 KB | Gzip-compressed inline payload |
9+
| Data Stream | >= 15 KB | Gzip-compressed via one-time data stream |
10+
11+
## Setup
12+
13+
1. Create a `.env.local` in this directory:
14+
```
15+
LIVEKIT_API_KEY=your-api-key
16+
LIVEKIT_API_SECRET=your-api-secret
17+
LIVEKIT_URL=wss://your-livekit-server.example.com
18+
```
19+
20+
2. Install and run:
21+
```bash
22+
pnpm install
23+
pnpm dev
24+
```
25+
26+
3. Open the URL shown by Vite (typically `http://localhost:5173`).
27+
28+
## Usage
29+
30+
1. Configure benchmark parameters in the UI:
31+
- **Payload Size**: use presets or enter a custom byte count
32+
- **Duration**: how long the benchmark runs (seconds)
33+
- **Concurrent Callers**: number of parallel async caller "threads"
34+
- **Delay Between Calls**: ms to wait between each call per thread
35+
36+
2. Click **Run Benchmark**. The page connects a caller and receiver to the same room, then the caller fires RPCs and verifies round-trip integrity via checksum.
37+
38+
3. Live stats update every 500ms. Click **Stop** to end early.
39+
40+
Everything runs in a single browser tab — no need for multiple tabs.

examples/rpc-benchmark/api.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import dotenv from 'dotenv';
2+
import express from 'express';
3+
import { AccessToken } from 'livekit-server-sdk';
4+
import type { Express } from 'express';
5+
6+
dotenv.config({ path: '.env.local' });
7+
8+
const LIVEKIT_API_KEY = process.env.LIVEKIT_API_KEY;
9+
const LIVEKIT_API_SECRET = process.env.LIVEKIT_API_SECRET;
10+
const LIVEKIT_URL = process.env.LIVEKIT_URL;
11+
12+
const app = express();
13+
app.use(express.json());
14+
15+
app.post('/api/get-token', async (req, res) => {
16+
const { identity, roomName } = req.body;
17+
18+
if (!LIVEKIT_API_KEY || !LIVEKIT_API_SECRET) {
19+
res.status(500).json({ error: 'Server misconfigured' });
20+
return;
21+
}
22+
23+
const token = new AccessToken(LIVEKIT_API_KEY, LIVEKIT_API_SECRET, {
24+
identity,
25+
});
26+
token.addGrant({
27+
room: roomName,
28+
roomJoin: true,
29+
canPublish: true,
30+
canSubscribe: true,
31+
});
32+
33+
res.json({
34+
token: await token.toJwt(),
35+
url: LIVEKIT_URL,
36+
});
37+
});
38+
39+
export const handler: Express = app;

examples/rpc-benchmark/index.html

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>LiveKit RPC Benchmark</title>
7+
<link rel="stylesheet" href="./styles.css" />
8+
</head>
9+
<body>
10+
<div class="container">
11+
<div class="title-row">
12+
<h1>LiveKit RPC Benchmark</h1>
13+
<div class="info-box">
14+
<span class="info-label">For informational use only</span>
15+
<label for="network">Network</label>
16+
<select id="network">
17+
<option value="" selected></option>
18+
<option value="Edge">Edge</option>
19+
<option value="3G">3G</option>
20+
<option value="LTE">LTE</option>
21+
<option value="Wifi">Wifi</option>
22+
</select>
23+
</div>
24+
</div>
25+
26+
<div class="controls">
27+
<div class="payload-row">
28+
<div class="control-group">
29+
<label for="payload-size">Payload Size (bytes)</label>
30+
<input type="number" id="payload-size" value="15360" min="1" step="1" />
31+
</div>
32+
<button class="preset-btn" data-size="500">500B</button>
33+
<button class="preset-btn" data-size="15360">15KB</button>
34+
<button class="preset-btn" data-size="102400">100KB</button>
35+
<button class="preset-btn" data-size="1048576">1MB</button>
36+
</div>
37+
<div class="control-row">
38+
<div class="control-group">
39+
<label for="duration">Duration (seconds)</label>
40+
<input type="number" id="duration" value="30" min="5" max="600" />
41+
</div>
42+
<div class="control-group">
43+
<label for="concurrency">Concurrent Callers</label>
44+
<input type="number" id="concurrency" value="3" min="1" max="20" />
45+
</div>
46+
<div class="control-group">
47+
<label for="delay">Delay Between Calls (ms)</label>
48+
<input type="number" id="delay" value="10" min="0" max="5000" />
49+
</div>
50+
</div>
51+
</div>
52+
53+
<button id="run-benchmark" class="btn">Run Benchmark</button>
54+
<button id="stop-benchmark" class="btn btn-danger" style="display: none;">Stop</button>
55+
56+
<div id="stats-area" style="display: none;">
57+
<h2>Live Stats</h2>
58+
<div class="stats-grid">
59+
<div class="stat">
60+
<span class="stat-label">Total Calls</span>
61+
<span class="stat-value" id="stat-total">0</span>
62+
</div>
63+
<div class="stat">
64+
<span class="stat-label">Successful</span>
65+
<span class="stat-value stat-success" id="stat-success">0</span>
66+
</div>
67+
<div class="stat">
68+
<span class="stat-label">Failed</span>
69+
<span class="stat-value stat-fail" id="stat-failed">0</span>
70+
</div>
71+
<div class="stat">
72+
<span class="stat-label">Success Rate</span>
73+
<span class="stat-value" id="stat-rate">-</span>
74+
</div>
75+
<div class="stat">
76+
<span class="stat-label">Avg Latency</span>
77+
<span class="stat-value" id="stat-avg-latency">-</span>
78+
</div>
79+
<div class="stat">
80+
<span class="stat-label">P50 Latency</span>
81+
<span class="stat-value" id="stat-p50">-</span>
82+
</div>
83+
<div class="stat">
84+
<span class="stat-label">P95 Latency</span>
85+
<span class="stat-value" id="stat-p95">-</span>
86+
</div>
87+
<div class="stat">
88+
<span class="stat-label">P99 Latency</span>
89+
<span class="stat-value" id="stat-p99">-</span>
90+
</div>
91+
<div class="stat">
92+
<span class="stat-label">Calls/sec</span>
93+
<span class="stat-value" id="stat-throughput">-</span>
94+
</div>
95+
<div class="stat">
96+
<span class="stat-label">Checksum Mismatches</span>
97+
<span class="stat-value stat-fail" id="stat-checksum">0</span>
98+
</div>
99+
<div class="stat">
100+
<span class="stat-label">Elapsed</span>
101+
<span class="stat-value" id="stat-elapsed">0s</span>
102+
</div>
103+
</div>
104+
</div>
105+
106+
<div id="log-area">
107+
<h2>Log</h2>
108+
<textarea id="log" rows="15" readonly></textarea>
109+
</div>
110+
</div>
111+
<script type="module" src="./rpc-benchmark.ts"></script>
112+
</body>
113+
</html>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "livekit-rpc-benchmark",
3+
"version": "1.0.0",
4+
"description": "Benchmark for LiveKit RPC with varying payload sizes",
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite",
8+
"build": "tsc && vite build",
9+
"preview": "vite preview"
10+
},
11+
"dependencies": {
12+
"cors": "^2.8.5",
13+
"dotenv": "^16.4.5",
14+
"express": "^5.2.1",
15+
"livekit-server-sdk": "^2.7.0",
16+
"vite": "^5.4.21",
17+
"vite-plugin-mix": "^0.4.0"
18+
},
19+
"devDependencies": {
20+
"@types/cors": "^2.8.17",
21+
"@types/express": "^5.0.0",
22+
"concurrently": "^8.2.0",
23+
"tsx": "^4.7.0",
24+
"typescript": "^5.4.5"
25+
}
26+
}

0 commit comments

Comments
 (0)