feat(scripts): enhance load test script for multi-part events (agent)

- Updated `scripts/agent/load-test.mjs` to simulate realistic video publishing flows by generating Video Post (Kind 30078), Video Mirror (Kind 1063), and NIP-71 Metadata (Kind 21/22) events for "heavy" load scenarios.
- Refactored the load generation loop to strictly separate cryptographic signing time from network transmission time, ensuring accurate performance metrics.
- Generated a baseline `artifacts/load-report.json` demonstrating ~100 events/sec throughput and sub-10ms signing latency.
- Verified execution against a local relay to prevent public network stress.

Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
google-labs-jules[bot]andPR0M3TH3AN committed 2026-01-26 19:41:50 +00:00
1 parent e970098edd
commit cec48811be
2 files changed
+114 -64

No files matched your search

+56 -56
View File
@@ -1,93 +1,93 @@
{
"timestamp": "2026-01-25T19:12:13.640Z",
"timestamp": "2026-01-26T19:39:32.887Z",
"config": {
"duration": 60,
"clients": 100,
"rate": 1,
"clients": 1000,
"rate": 0.1,
"relay": "ws://localhost:8889",
"force": false
},
"metrics": {
"total_sent": 6219,
"total_received": 6219,
"total_sent": 6467,
"total_received": 6467,
"errors": 0,
"throughput_sent": 103.65,
"throughput_recv": 103.65,
"throughput_sent": 107.78333333333333,
"throughput_recv": 107.78333333333333,
"latency_ms": {
"p50": 0.4525159999998323,
"p95": 0.9470979999969131,
"p99": 7.444698999999673
"p50": 0.9700979999979609,
"p95": 14.598196999999345,
"p99": 27.9113440000001
},
"operation_times_ms": {
"build_avg": 0.05414333365494229,
"sign_avg": 5.486003140054635
"build_avg": 0.10325683753031617,
"sign_avg": 6.474848927014066
},
"resource_usage": [
{
"timestamp": 1769368278643,
"cpuPercent": 63.94,
"rss": 97239040,
"heapUsed": 16337816
"timestamp": 1769456317885,
"cpuPercent": 74.54,
"rss": 129236992,
"heapUsed": 26275344
},
{
"timestamp": 1769368283643,
"cpuPercent": 64.36,
"rss": 98402304,
"heapUsed": 20259576
"timestamp": 1769456322898,
"cpuPercent": 71.77,
"rss": 130256896,
"heapUsed": 30151424
},
{
"timestamp": 1769368288642,
"cpuPercent": 63.86,
"rss": 98762752,
"heapUsed": 17659632
"timestamp": 1769456327916,
"cpuPercent": 70.52,
"rss": 131235840,
"heapUsed": 30829208
},
{
"timestamp": 1769368293643,
"cpuPercent": 61.32,
"rss": 99790848,
"heapUsed": 18155016
"timestamp": 1769456332917,
"cpuPercent": 72.98,
"rss": 131637248,
"heapUsed": 38053280
},
{
"timestamp": 1769368298645,
"cpuPercent": 61.19,
"rss": 100999168,
"heapUsed": 15496016
"timestamp": 1769456337917,
"cpuPercent": 78.13,
"rss": 132292608,
"heapUsed": 25903752
},
{
"timestamp": 1769368303646,
"cpuPercent": 63.12,
"rss": 102313984,
"heapUsed": 16290368
"timestamp": 1769456342918,
"cpuPercent": 92.71,
"rss": 133566464,
"heapUsed": 28111320
},
{
"timestamp": 1769368308649,
"cpuPercent": 61.61,
"rss": 105914368,
"heapUsed": 22963352
"timestamp": 1769456347922,
"cpuPercent": 94.4,
"rss": 133959680,
"heapUsed": 33235048
},
{
"timestamp": 1769368313653,
"cpuPercent": 60.4,
"rss": 106831872,
"heapUsed": 21787144
"timestamp": 1769456352924,
"cpuPercent": 77.78,
"rss": 134717440,
"heapUsed": 27477160
},
{
"timestamp": 1769368318653,
"cpuPercent": 60.86,
"rss": 120463360,
"heapUsed": 17511208
"timestamp": 1769456357925,
"cpuPercent": 86.22,
"rss": 135241728,
"heapUsed": 36644992
},
{
"timestamp": 1769368323657,
"cpuPercent": 60.52,
"rss": 120987648,
"heapUsed": 19454880
"timestamp": 1769456362926,
"cpuPercent": 79.21,
"rss": 136028160,
"heapUsed": 28313856
},
{
"timestamp": 1769368328657,
"cpuPercent": 59.65,
"rss": 121643008,
"heapUsed": 21375032
"timestamp": 1769456367927,
"cpuPercent": 71.57,
"rss": 136814592,
"heapUsed": 39710304
}
],
"error_breakdown": {}
+58 -8
View File
@@ -12,7 +12,8 @@ import { performance } from 'node:perf_hooks';
global.NostrTools = NostrTools;
// Import Schema Builders
import { buildVideoPostEvent, buildViewEvent } from '../../js/nostrEventSchemas.js';
import { buildVideoPostEvent, buildViewEvent, buildVideoMirrorEvent } from '../../js/nostrEventSchemas.js';
import { buildNip71VideoEvent } from '../../js/nostr/nip71.js';
// --- Configuration ---
const ARTIFACTS_DIR = 'artifacts';
@@ -253,6 +254,8 @@ async function run() {
const now = Math.floor(Date.now() / 1000);
const hexPk = client.pk;
const eventsToSend = [];
if (isHeavy) {
// Video Post
const content = {
@@ -260,17 +263,56 @@ async function run() {
title: `Load Test Video ${Date.now()}`,
description: 'A description for load testing purposes. '.repeat(50),
magnet: `magnet:?xt=urn:btih:${Math.random().toString(16).slice(2).repeat(10)}`,
url: `https://example.com/video-${Date.now()}.mp4`,
thumbnail: `https://example.com/thumb-${Date.now()}.jpg`,
mode: 'live',
videoRootId: `load-${Date.now()}-${Math.random()}`,
isNsfw: false,
isForKids: false,
};
event = buildVideoPostEvent({
const rootEvent = buildVideoPostEvent({
pubkey: hexPk,
created_at: now,
content,
dTagValue: content.videoRootId
});
eventsToSend.push(rootEvent);
// Mirror Event (NIP-94)
const mirrorEvent = buildVideoMirrorEvent({
pubkey: hexPk,
created_at: now,
tags: [['e', rootEvent.id], ['d', content.videoRootId]],
content: {
url: content.url,
magnet: content.magnet,
thumbnail: content.thumbnail,
title: content.title
}
});
eventsToSend.push(mirrorEvent);
// NIP-71 Metadata
const nip71Event = buildNip71VideoEvent({
metadata: {
kind: 21,
title: content.title,
summary: content.description.slice(0, 200),
publishedAt: now,
hashtags: ['loadtest', 'stress'],
},
pubkey: hexPk,
title: content.title,
createdAt: now,
pointerIdentifiers: {
videoRootId: content.videoRootId,
dTag: content.videoRootId,
eventId: rootEvent.id
}
});
if (nip71Event) eventsToSend.push(nip71Event);
} else {
// View Event
event = buildViewEvent({
@@ -279,18 +321,26 @@ async function run() {
pointerValue: `load-video-${Math.random()}`,
pointerTag: ['d', `load-video-${Math.random()}`]
});
eventsToSend.push(event);
}
metrics.operationTimes.build.push(performance.now() - buildStart);
// Sign
const signStart = performance.now();
const signedEvent = NostrTools.finalizeEvent(event, client.sk);
metrics.operationTimes.sign.push(performance.now() - signStart);
const signedEvents = [];
for (const ev of eventsToSend) {
const t0 = performance.now();
const signed = NostrTools.finalizeEvent(ev, client.sk);
const t1 = performance.now();
metrics.operationTimes.sign.push(t1 - t0);
signedEvents.push(signed);
}
// Publish
client.pendingEvents.set(signedEvent.id, performance.now());
client.ws.send(JSON.stringify(['EVENT', signedEvent]));
metrics.sent++;
for (const signedEvent of signedEvents) {
client.pendingEvents.set(signedEvent.id, performance.now());
client.ws.send(JSON.stringify(['EVENT', signedEvent]));
metrics.sent++;
}
} catch (e) {
console.error('Error generating/sending event:', e);