mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 16:02:26 +00:00
Merge pull request #2111 from PR0M3TH3AN/ai/load-test-20260205-6733218743642638407
feat: Add load test script and report
This commit is contained in:
2 files changed
+117
-70
No files matched your search
+74
-52
@@ -1,77 +1,99 @@
|
||||
{
|
||||
"meta": {
|
||||
"clients": 1000,
|
||||
"duration": 60,
|
||||
"targetRatePerClient": 0.5
|
||||
"clients": 50,
|
||||
"duration": 10,
|
||||
"targetTotalRate": 50,
|
||||
"ratePerClient": 1
|
||||
},
|
||||
"results": {
|
||||
"totalSent": 9880,
|
||||
"totalReceivedByObserver": 9212,
|
||||
"totalSent": 545,
|
||||
"totalReceivedByObserver": 554,
|
||||
"totalErrors": 0,
|
||||
"errorRate": 0,
|
||||
"avgLatencyMs": 633.5714285714286,
|
||||
"maxLatencyMs": 4352,
|
||||
"avgSignTimeMs": 5.312883614738433
|
||||
"avgLatencyMs": 5.888888888888889,
|
||||
"maxLatencyMs": 8,
|
||||
"avgSignTimeMs": 5.534525739479302,
|
||||
"hot_functions": [
|
||||
{
|
||||
"name": "Event Signing (Client)",
|
||||
"avgTimeMs": 5.534525739479302,
|
||||
"calls": 545
|
||||
}
|
||||
]
|
||||
},
|
||||
"bottlenecks": [
|
||||
"High Average Latency (>500ms)",
|
||||
"Cryptographic Bottleneck (Avg Sign Time 5.31ms > 5ms)"
|
||||
"Cryptographic Bottleneck (Avg Sign Time 5.53ms > 5ms)"
|
||||
],
|
||||
"metrics": {
|
||||
"timestamps": [
|
||||
"2026-02-02T19:20:53.413Z",
|
||||
"2026-02-02T19:21:05.252Z",
|
||||
"2026-02-02T19:21:09.391Z",
|
||||
"2026-02-02T19:21:17.727Z",
|
||||
"2026-02-02T19:21:25.657Z",
|
||||
"2026-02-02T19:21:37.832Z",
|
||||
"2026-02-02T19:21:46.152Z"
|
||||
"2026-02-05T19:34:52.639Z",
|
||||
"2026-02-05T19:34:53.638Z",
|
||||
"2026-02-05T19:34:54.641Z",
|
||||
"2026-02-05T19:34:55.649Z",
|
||||
"2026-02-05T19:34:56.649Z",
|
||||
"2026-02-05T19:34:57.649Z",
|
||||
"2026-02-05T19:34:58.672Z",
|
||||
"2026-02-05T19:34:59.671Z",
|
||||
"2026-02-05T19:35:00.672Z"
|
||||
],
|
||||
"cpu": [
|
||||
1.805,
|
||||
1131.911,
|
||||
420.9089,
|
||||
851.5216,
|
||||
798.2084,
|
||||
1222.0326,
|
||||
835.8484
|
||||
47.1817,
|
||||
40.502,
|
||||
37.7894,
|
||||
36.4607,
|
||||
36.4638,
|
||||
36.3083,
|
||||
41.62,
|
||||
35.6474,
|
||||
35.4054
|
||||
],
|
||||
"memory": [
|
||||
17.17798614501953,
|
||||
27.51868438720703,
|
||||
19.160232543945312,
|
||||
23.5911865234375,
|
||||
19.544578552246094,
|
||||
33.026039123535156,
|
||||
20.853515625
|
||||
12.619827270507812,
|
||||
12.327117919921875,
|
||||
16.86083221435547,
|
||||
13.562667846679688,
|
||||
16.10260009765625,
|
||||
11.007034301757812,
|
||||
14.259078979492188,
|
||||
14.051017761230469,
|
||||
15.620246887207031
|
||||
],
|
||||
"latency": [
|
||||
14,
|
||||
4352,
|
||||
13,
|
||||
12,
|
||||
15,
|
||||
15,
|
||||
14
|
||||
8,
|
||||
6,
|
||||
6,
|
||||
5,
|
||||
6,
|
||||
6,
|
||||
6,
|
||||
5,
|
||||
5
|
||||
],
|
||||
"throughput": [
|
||||
1,
|
||||
1119,
|
||||
1257,
|
||||
1356,
|
||||
1330,
|
||||
1448,
|
||||
1345
|
||||
60,
|
||||
59,
|
||||
64,
|
||||
63,
|
||||
62,
|
||||
62,
|
||||
63,
|
||||
60,
|
||||
61
|
||||
],
|
||||
"avgSignTime": [
|
||||
0,
|
||||
6.01051988318584,
|
||||
5.731465363770286,
|
||||
5.82640474538752,
|
||||
5.684893507148126,
|
||||
8.042285998617778,
|
||||
5.894615805059483
|
||||
6.518746254237273,
|
||||
5.50673901724142,
|
||||
5.487499650793643,
|
||||
5.261303790322589,
|
||||
5.267506754098338,
|
||||
5.199484229508195,
|
||||
6.068795209677216,
|
||||
5.2998529661016915,
|
||||
5.2008037833333525
|
||||
]
|
||||
},
|
||||
"remediation": [
|
||||
"Client-side event signing is slow. Review cryptographic library (nostr-tools) usage or client hardware capabilities."
|
||||
],
|
||||
"requiresSecurityReview": true
|
||||
}
|
||||
+43
-18
@@ -1,7 +1,7 @@
|
||||
import './setup-test-env.js';
|
||||
import { WebSocket } from 'ws';
|
||||
import { generateSecretKey, getPublicKey, finalizeEvent } from 'nostr-tools';
|
||||
import { buildVideoPostEvent, buildViewEvent } from '../../js/nostrEventSchemas.js';
|
||||
import { buildVideoPostEvent, buildViewEvent, buildVideoMirrorEvent } from '../../js/nostrEventSchemas.js';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { spawn } from 'child_process';
|
||||
@@ -73,41 +73,62 @@ class LoadBot {
|
||||
publish() {
|
||||
if (!this.connected || this.ws.readyState !== WebSocket.OPEN) return;
|
||||
|
||||
// Mix: 80% View Events (Small), 20% Video Post (Large)
|
||||
// Mix: 80% View Events (Small), 20% Multi-part Video (Large)
|
||||
const isLarge = Math.random() < 0.2;
|
||||
let eventTemplate;
|
||||
const eventsToSend = [];
|
||||
|
||||
if (isLarge) {
|
||||
eventTemplate = buildVideoPostEvent({
|
||||
const videoRootId = `root-${this.id}-${Date.now()}`;
|
||||
// 1. Video Metadata (Kind 30078)
|
||||
const videoEvent = buildVideoPostEvent({
|
||||
pubkey: this.pk,
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
dTagValue: `load-${this.id}-${Date.now()}`,
|
||||
dTagValue: videoRootId,
|
||||
content: {
|
||||
version: 3,
|
||||
title: `Load Test Video ${Date.now()}`,
|
||||
description: 'A' .repeat(500), // Filler content
|
||||
videoRootId: `root-${this.id}-${Date.now()}`,
|
||||
description: 'A'.repeat(5000), // Filler content ~5KB
|
||||
videoRootId: videoRootId,
|
||||
magnet: `magnet:?xt=urn:btih:${'a'.repeat(40)}&dn=test`
|
||||
}
|
||||
});
|
||||
eventsToSend.push(videoEvent);
|
||||
|
||||
// 2. Video Mirror (Kind 1063) - Simulated "multi-part"
|
||||
const mirrorEvent = buildVideoMirrorEvent({
|
||||
pubkey: this.pk,
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
tags: [
|
||||
['a', `30078:${this.pk}:${videoRootId}`]
|
||||
],
|
||||
content: {
|
||||
description: 'Mirror filler ' + 'B'.repeat(100)
|
||||
}
|
||||
});
|
||||
eventsToSend.push(mirrorEvent);
|
||||
|
||||
} else {
|
||||
eventTemplate = buildViewEvent({
|
||||
// View Event
|
||||
const viewEvent = buildViewEvent({
|
||||
pubkey: this.pk,
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
content: 'view-ping',
|
||||
dedupeTag: `view-${this.id}-${Date.now()}`
|
||||
});
|
||||
eventsToSend.push(viewEvent);
|
||||
}
|
||||
|
||||
try {
|
||||
const t0 = performance.now();
|
||||
const signedEvent = finalizeEvent(eventTemplate, this.sk);
|
||||
const t1 = performance.now();
|
||||
this.signTimes.push(t1 - t0);
|
||||
for (const ev of eventsToSend) {
|
||||
const t0 = performance.now();
|
||||
const signedEvent = finalizeEvent(ev, this.sk);
|
||||
const t1 = performance.now();
|
||||
this.signTimes.push(t1 - t0);
|
||||
|
||||
const msg = JSON.stringify(['EVENT', signedEvent]);
|
||||
this.ws.send(msg);
|
||||
this.sentCount++;
|
||||
const msg = JSON.stringify(['EVENT', signedEvent]);
|
||||
this.ws.send(msg);
|
||||
this.sentCount++;
|
||||
}
|
||||
} catch (e) {
|
||||
this.errors++;
|
||||
}
|
||||
@@ -195,12 +216,15 @@ async function runLoadTest() {
|
||||
const args = process.argv.slice(2);
|
||||
const clientsArg = args.find(a => a.startsWith('--clients='));
|
||||
const durationArg = args.find(a => a.startsWith('--duration='));
|
||||
const rateArg = args.find(a => a.startsWith('--rate='));
|
||||
|
||||
const NUM_CLIENTS = clientsArg ? parseInt(clientsArg.split('=')[1]) : 1000;
|
||||
const DURATION_SEC = durationArg ? parseInt(durationArg.split('=')[1]) : 60; // Default 1 min
|
||||
const TARGET_RATE = 0.5; // Events per second per bot (0.5 * 1000 = 500 events/sec total)
|
||||
const TOTAL_TARGET_RATE = rateArg ? parseInt(rateArg.split('=')[1]) : 500; // Events/sec total
|
||||
const RATE_PER_CLIENT = TOTAL_TARGET_RATE / NUM_CLIENTS;
|
||||
|
||||
console.log(`[Load Test] Starting with ${NUM_CLIENTS} clients for ${DURATION_SEC}s...`);
|
||||
console.log(`[Load Test] Target Rate: ${TOTAL_TARGET_RATE} events/s (${RATE_PER_CLIENT.toFixed(2)}/client)`);
|
||||
|
||||
// Ensure artifacts dir
|
||||
if (!fs.existsSync(ARTIFACTS_DIR)) fs.mkdirSync(ARTIFACTS_DIR);
|
||||
@@ -222,7 +246,7 @@ async function runLoadTest() {
|
||||
const bots = [];
|
||||
console.log('[Load Test] Spawning bots...');
|
||||
for (let i = 0; i < NUM_CLIENTS; i++) {
|
||||
const bot = new LoadBot(i, RELAY_URL, TARGET_RATE);
|
||||
const bot = new LoadBot(i, RELAY_URL, RATE_PER_CLIENT);
|
||||
bots.push(bot);
|
||||
}
|
||||
|
||||
@@ -313,7 +337,8 @@ async function runLoadTest() {
|
||||
meta: {
|
||||
clients: NUM_CLIENTS,
|
||||
duration: DURATION_SEC,
|
||||
targetRatePerClient: TARGET_RATE
|
||||
targetTotalRate: TOTAL_TARGET_RATE,
|
||||
ratePerClient: RATE_PER_CLIENT
|
||||
},
|
||||
results: {
|
||||
totalSent,
|
||||
|
||||
Reference in new issue
Block a user