@ruvector/edge-net 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1239 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Edge-Net Plugin System Performance Benchmarks
4
+ *
5
+ * Comprehensive benchmarks measuring:
6
+ * - Plugin loading performance (cold/warm/bundle)
7
+ * - Plugin execution throughput
8
+ * - Sandbox overhead
9
+ * - Memory usage patterns
10
+ *
11
+ * Run: node tests/plugin-benchmark.js
12
+ *
13
+ * @module @ruvector/edge-net/tests/plugin-benchmark
14
+ */
15
+
16
+ import { performance } from 'perf_hooks';
17
+ import { PluginLoader, PluginManager } from '../plugins/plugin-loader.js';
18
+ import { CompressionPlugin } from '../plugins/implementations/compression.js';
19
+ import { E2EEncryptionPlugin } from '../plugins/implementations/e2e-encryption.js';
20
+ import { SwarmIntelligencePlugin } from '../plugins/implementations/swarm-intelligence.js';
21
+ import { FederatedLearningPlugin } from '../plugins/implementations/federated-learning.js';
22
+ import { ReputationStakingPlugin } from '../plugins/implementations/reputation-staking.js';
23
+ import { PLUGIN_CATALOG, PLUGIN_BUNDLES } from '../plugins/plugin-manifest.js';
24
+
25
+ // ============================================
26
+ // BENCHMARK CONFIGURATION
27
+ // ============================================
28
+
29
+ const CONFIG = {
30
+ // Iterations for statistical significance
31
+ warmupIterations: 10,
32
+ benchmarkIterations: 100,
33
+
34
+ // Data sizes for throughput tests
35
+ dataSizes: {
36
+ small: 1024, // 1 KB
37
+ medium: 65536, // 64 KB
38
+ large: 1048576, // 1 MB
39
+ },
40
+
41
+ // Swarm intelligence settings
42
+ swarm: {
43
+ populationSize: 50,
44
+ dimensions: 10,
45
+ iterations: 100,
46
+ },
47
+
48
+ // Federated learning settings
49
+ federated: {
50
+ localDataSize: 1000,
51
+ participants: 5,
52
+ epochs: 5,
53
+ },
54
+
55
+ // Reputation staking settings
56
+ staking: {
57
+ operations: 1000,
58
+ },
59
+
60
+ // Memory test settings
61
+ memoryOperations: 1000,
62
+ };
63
+
64
+ // ============================================
65
+ // UTILITY FUNCTIONS
66
+ // ============================================
67
+
68
+ function formatBytes(bytes) {
69
+ if (bytes < 1024) return `${bytes} B`;
70
+ if (bytes < 1048576) return `${(bytes / 1024).toFixed(2)} KB`;
71
+ return `${(bytes / 1048576).toFixed(2)} MB`;
72
+ }
73
+
74
+ function formatNumber(num) {
75
+ if (num >= 1000000) return `${(num / 1000000).toFixed(2)}M`;
76
+ if (num >= 1000) return `${(num / 1000).toFixed(2)}K`;
77
+ return num.toFixed(2);
78
+ }
79
+
80
+ function generateRandomData(size) {
81
+ const buffer = Buffer.alloc(size);
82
+ for (let i = 0; i < size; i++) {
83
+ buffer[i] = Math.floor(Math.random() * 256);
84
+ }
85
+ return buffer;
86
+ }
87
+
88
+ function generateCompressibleData(size) {
89
+ // Data with repeating patterns (compresses well)
90
+ const buffer = Buffer.alloc(size);
91
+ const patterns = [0x00, 0xFF, 0xAA, 0x55];
92
+ for (let i = 0; i < size; i++) {
93
+ // Create runs of repeating bytes
94
+ const runLength = Math.floor(Math.random() * 32) + 4;
95
+ const pattern = patterns[Math.floor(Math.random() * patterns.length)];
96
+ for (let j = 0; j < runLength && i + j < size; j++) {
97
+ buffer[i + j] = pattern;
98
+ }
99
+ i += runLength - 1;
100
+ }
101
+ return buffer;
102
+ }
103
+
104
+ function getMemoryUsage() {
105
+ const usage = process.memoryUsage();
106
+ return {
107
+ heapUsed: usage.heapUsed,
108
+ heapTotal: usage.heapTotal,
109
+ external: usage.external,
110
+ rss: usage.rss,
111
+ };
112
+ }
113
+
114
+ function calculateStats(times) {
115
+ const sorted = [...times].sort((a, b) => a - b);
116
+ const sum = sorted.reduce((a, b) => a + b, 0);
117
+ const mean = sum / sorted.length;
118
+ const variance = sorted.reduce((acc, t) => acc + Math.pow(t - mean, 2), 0) / sorted.length;
119
+ const stdDev = Math.sqrt(variance);
120
+
121
+ return {
122
+ mean,
123
+ median: sorted[Math.floor(sorted.length / 2)],
124
+ min: sorted[0],
125
+ max: sorted[sorted.length - 1],
126
+ stdDev,
127
+ p95: sorted[Math.floor(sorted.length * 0.95)],
128
+ p99: sorted[Math.floor(sorted.length * 0.99)],
129
+ };
130
+ }
131
+
132
+ // ============================================
133
+ // BENCHMARK RESULTS COLLECTOR
134
+ // ============================================
135
+
136
+ class BenchmarkResults {
137
+ constructor() {
138
+ this.results = new Map();
139
+ this.startTime = Date.now();
140
+ }
141
+
142
+ add(category, name, metrics) {
143
+ if (!this.results.has(category)) {
144
+ this.results.set(category, new Map());
145
+ }
146
+ this.results.get(category).set(name, metrics);
147
+ }
148
+
149
+ generateReport() {
150
+ const report = {
151
+ timestamp: new Date().toISOString(),
152
+ duration: Date.now() - this.startTime,
153
+ nodeVersion: process.version,
154
+ platform: process.platform,
155
+ arch: process.arch,
156
+ categories: {},
157
+ };
158
+
159
+ for (const [category, metrics] of this.results) {
160
+ report.categories[category] = {};
161
+ for (const [name, data] of metrics) {
162
+ report.categories[category][name] = data;
163
+ }
164
+ }
165
+
166
+ return report;
167
+ }
168
+ }
169
+
170
+ // ============================================
171
+ // PLUGIN LOADING BENCHMARKS
172
+ // ============================================
173
+
174
+ async function benchmarkPluginLoading(results) {
175
+ console.log('\n--- Plugin Loading Performance ---\n');
176
+
177
+ // Cold load time (first load, no cache)
178
+ console.log('Testing cold load times...');
179
+ const coldLoadTimes = {};
180
+
181
+ for (const pluginId of Object.keys(PLUGIN_CATALOG)) {
182
+ PluginManager.reset();
183
+ const loader = PluginManager.getInstance({ verifySignatures: false });
184
+
185
+ global.gc?.(); // Force GC if available
186
+
187
+ const start = performance.now();
188
+ try {
189
+ await loader.load(pluginId);
190
+ coldLoadTimes[pluginId] = performance.now() - start;
191
+ } catch (e) {
192
+ coldLoadTimes[pluginId] = null; // Plugin not loadable
193
+ }
194
+ }
195
+
196
+ // Filter out null values and calculate stats
197
+ const validColdTimes = Object.values(coldLoadTimes).filter(t => t !== null);
198
+ results.add('Plugin Loading', 'Cold Load Times (ms)', coldLoadTimes);
199
+ results.add('Plugin Loading', 'Cold Load Stats', calculateStats(validColdTimes));
200
+
201
+ // Warm load time (already loaded/cached)
202
+ console.log('Testing warm load times...');
203
+ const warmLoadTimes = {};
204
+
205
+ for (const pluginId of Object.keys(PLUGIN_CATALOG)) {
206
+ const loader = PluginManager.getInstance();
207
+ const times = [];
208
+
209
+ for (let i = 0; i < CONFIG.warmupIterations; i++) {
210
+ const start = performance.now();
211
+ try {
212
+ await loader.load(pluginId); // Should return cached
213
+ times.push(performance.now() - start);
214
+ } catch (e) {
215
+ // Skip
216
+ }
217
+ }
218
+
219
+ if (times.length > 0) {
220
+ warmLoadTimes[pluginId] = calculateStats(times);
221
+ }
222
+ }
223
+
224
+ results.add('Plugin Loading', 'Warm Load Times (ms)', warmLoadTimes);
225
+
226
+ // Bundle load time
227
+ console.log('Testing bundle load times...');
228
+ const bundleLoadTimes = {};
229
+
230
+ for (const bundleName of Object.keys(PLUGIN_BUNDLES)) {
231
+ PluginManager.reset();
232
+ const loader = PluginManager.getInstance({ verifySignatures: false });
233
+
234
+ global.gc?.();
235
+
236
+ const start = performance.now();
237
+ try {
238
+ await loader.loadBundle(bundleName);
239
+ bundleLoadTimes[bundleName] = performance.now() - start;
240
+ } catch (e) {
241
+ bundleLoadTimes[bundleName] = null;
242
+ }
243
+ }
244
+
245
+ results.add('Plugin Loading', 'Bundle Load Times (ms)', bundleLoadTimes);
246
+
247
+ // Memory footprint per plugin
248
+ console.log('Measuring plugin memory footprint...');
249
+ const memoryFootprints = {};
250
+
251
+ for (const pluginId of Object.keys(PLUGIN_CATALOG)) {
252
+ PluginManager.reset();
253
+ global.gc?.();
254
+
255
+ const beforeMem = getMemoryUsage();
256
+ const loader = PluginManager.getInstance({ verifySignatures: false });
257
+
258
+ try {
259
+ await loader.load(pluginId);
260
+ global.gc?.();
261
+
262
+ const afterMem = getMemoryUsage();
263
+ memoryFootprints[pluginId] = afterMem.heapUsed - beforeMem.heapUsed;
264
+ } catch (e) {
265
+ memoryFootprints[pluginId] = null;
266
+ }
267
+ }
268
+
269
+ results.add('Plugin Loading', 'Memory Footprint (bytes)', memoryFootprints);
270
+
271
+ console.log(' Cold load avg:', calculateStats(validColdTimes).mean.toFixed(3), 'ms');
272
+ }
273
+
274
+ // ============================================
275
+ // COMPRESSION PLUGIN BENCHMARKS
276
+ // ============================================
277
+
278
+ async function benchmarkCompression(results) {
279
+ console.log('\n--- CompressionPlugin Performance ---\n');
280
+
281
+ const plugin = new CompressionPlugin({ threshold: 0 }); // Disable threshold
282
+
283
+ for (const [sizeName, size] of Object.entries(CONFIG.dataSizes)) {
284
+ console.log(`Testing ${sizeName} data (${formatBytes(size)})...`);
285
+
286
+ // Test with compressible data
287
+ const compressibleData = generateCompressibleData(size);
288
+ const randomData = generateRandomData(size);
289
+
290
+ // Compression throughput (compressible)
291
+ const compressTimes = [];
292
+ const compressedSizes = [];
293
+
294
+ for (let i = 0; i < CONFIG.benchmarkIterations; i++) {
295
+ const start = performance.now();
296
+ const result = plugin.compress(compressibleData);
297
+ compressTimes.push(performance.now() - start);
298
+ compressedSizes.push(result.compressedSize || compressibleData.length);
299
+ }
300
+
301
+ const compressStats = calculateStats(compressTimes);
302
+ const avgCompressedSize = compressedSizes.reduce((a, b) => a + b, 0) / compressedSizes.length;
303
+ const compressionRatio = avgCompressedSize / size;
304
+ const throughputMBs = (size / 1048576) / (compressStats.mean / 1000);
305
+
306
+ results.add('Compression', `${sizeName} Compress (compressible)`, {
307
+ throughputMBs: throughputMBs.toFixed(2),
308
+ avgTimeMs: compressStats.mean.toFixed(3),
309
+ p95Ms: compressStats.p95.toFixed(3),
310
+ compressionRatio: compressionRatio.toFixed(3),
311
+ });
312
+
313
+ // Decompression throughput
314
+ const compressedData = plugin.compress(compressibleData);
315
+ const decompressTimes = [];
316
+
317
+ for (let i = 0; i < CONFIG.benchmarkIterations; i++) {
318
+ const start = performance.now();
319
+ plugin.decompress(compressedData.data, compressedData.compressed);
320
+ decompressTimes.push(performance.now() - start);
321
+ }
322
+
323
+ const decompressStats = calculateStats(decompressTimes);
324
+ const decompressThroughput = (size / 1048576) / (decompressStats.mean / 1000);
325
+
326
+ results.add('Compression', `${sizeName} Decompress`, {
327
+ throughputMBs: decompressThroughput.toFixed(2),
328
+ avgTimeMs: decompressStats.mean.toFixed(3),
329
+ p95Ms: decompressStats.p95.toFixed(3),
330
+ });
331
+
332
+ // Random data (less compressible)
333
+ const randomCompressTimes = [];
334
+ for (let i = 0; i < CONFIG.benchmarkIterations; i++) {
335
+ const start = performance.now();
336
+ plugin.compress(randomData);
337
+ randomCompressTimes.push(performance.now() - start);
338
+ }
339
+
340
+ const randomCompressStats = calculateStats(randomCompressTimes);
341
+ results.add('Compression', `${sizeName} Compress (random)`, {
342
+ throughputMBs: ((size / 1048576) / (randomCompressStats.mean / 1000)).toFixed(2),
343
+ avgTimeMs: randomCompressStats.mean.toFixed(3),
344
+ });
345
+ }
346
+
347
+ console.log(' Compression benchmarks complete');
348
+ }
349
+
350
+ // ============================================
351
+ // E2E ENCRYPTION PLUGIN BENCHMARKS
352
+ // ============================================
353
+
354
+ async function benchmarkEncryption(results) {
355
+ console.log('\n--- E2EEncryptionPlugin Performance ---\n');
356
+
357
+ const plugin = new E2EEncryptionPlugin({ forwardSecrecy: false });
358
+ await plugin.init();
359
+
360
+ // Setup sessions
361
+ const peers = ['peer1', 'peer2', 'peer3', 'peer4', 'peer5'];
362
+ for (const peer of peers) {
363
+ await plugin.establishSession(peer, 'dummy-public-key');
364
+ }
365
+
366
+ for (const [sizeName, size] of Object.entries(CONFIG.dataSizes)) {
367
+ console.log(`Testing ${sizeName} data (${formatBytes(size)})...`);
368
+
369
+ const testData = generateRandomData(size).toString('base64');
370
+
371
+ // Encryption ops/sec
372
+ const encryptTimes = [];
373
+ for (let i = 0; i < CONFIG.benchmarkIterations; i++) {
374
+ const peer = peers[i % peers.length];
375
+ const start = performance.now();
376
+ plugin.encrypt(peer, testData);
377
+ encryptTimes.push(performance.now() - start);
378
+ }
379
+
380
+ const encryptStats = calculateStats(encryptTimes);
381
+ const encryptOpsPerSec = 1000 / encryptStats.mean;
382
+
383
+ results.add('Encryption', `${sizeName} Encrypt`, {
384
+ opsPerSec: formatNumber(encryptOpsPerSec),
385
+ avgTimeMs: encryptStats.mean.toFixed(3),
386
+ p95Ms: encryptStats.p95.toFixed(3),
387
+ throughputMBs: ((size / 1048576) / (encryptStats.mean / 1000)).toFixed(2),
388
+ });
389
+
390
+ // Decryption ops/sec
391
+ const encrypted = plugin.encrypt('peer1', testData);
392
+ const decryptTimes = [];
393
+
394
+ for (let i = 0; i < CONFIG.benchmarkIterations; i++) {
395
+ const start = performance.now();
396
+ plugin.decrypt('peer1', encrypted);
397
+ decryptTimes.push(performance.now() - start);
398
+ }
399
+
400
+ const decryptStats = calculateStats(decryptTimes);
401
+ const decryptOpsPerSec = 1000 / decryptStats.mean;
402
+
403
+ results.add('Encryption', `${sizeName} Decrypt`, {
404
+ opsPerSec: formatNumber(decryptOpsPerSec),
405
+ avgTimeMs: decryptStats.mean.toFixed(3),
406
+ p95Ms: decryptStats.p95.toFixed(3),
407
+ throughputMBs: ((size / 1048576) / (decryptStats.mean / 1000)).toFixed(2),
408
+ });
409
+ }
410
+
411
+ // Session establishment overhead
412
+ console.log('Testing session establishment...');
413
+ const sessionTimes = [];
414
+ for (let i = 0; i < CONFIG.benchmarkIterations; i++) {
415
+ const start = performance.now();
416
+ await plugin.establishSession(`test-peer-${i}`, 'dummy-key');
417
+ sessionTimes.push(performance.now() - start);
418
+ }
419
+
420
+ const sessionStats = calculateStats(sessionTimes);
421
+ results.add('Encryption', 'Session Establishment', {
422
+ opsPerSec: formatNumber(1000 / sessionStats.mean),
423
+ avgTimeMs: sessionStats.mean.toFixed(3),
424
+ p95Ms: sessionStats.p95.toFixed(3),
425
+ });
426
+
427
+ await plugin.destroy();
428
+ console.log(' Encryption benchmarks complete');
429
+ }
430
+
431
+ // ============================================
432
+ // SWARM INTELLIGENCE PLUGIN BENCHMARKS
433
+ // ============================================
434
+
435
+ async function benchmarkSwarmIntelligence(results) {
436
+ console.log('\n--- SwarmIntelligencePlugin Performance ---\n');
437
+
438
+ const algorithms = ['pso', 'ga', 'de', 'aco'];
439
+
440
+ for (const algorithm of algorithms) {
441
+ console.log(`Testing ${algorithm.toUpperCase()} algorithm...`);
442
+
443
+ const plugin = new SwarmIntelligencePlugin({
444
+ algorithm,
445
+ populationSize: CONFIG.swarm.populationSize,
446
+ iterations: CONFIG.swarm.iterations,
447
+ dimensions: CONFIG.swarm.dimensions,
448
+ });
449
+
450
+ // Single step performance
451
+ const stepTimes = [];
452
+ const swarm = plugin.createSwarm('bench-swarm', {
453
+ algorithm,
454
+ dimensions: CONFIG.swarm.dimensions,
455
+ fitnessFunction: (pos) => pos.reduce((sum, x) => sum + x * x, 0),
456
+ });
457
+
458
+ for (let i = 0; i < CONFIG.benchmarkIterations; i++) {
459
+ const start = performance.now();
460
+ plugin.step('bench-swarm');
461
+ stepTimes.push(performance.now() - start);
462
+ }
463
+
464
+ const stepStats = calculateStats(stepTimes);
465
+ const iterationsPerSec = 1000 / stepStats.mean;
466
+
467
+ results.add('Swarm Intelligence', `${algorithm.toUpperCase()} Step`, {
468
+ iterationsPerSec: formatNumber(iterationsPerSec),
469
+ avgTimeMs: stepStats.mean.toFixed(3),
470
+ p95Ms: stepStats.p95.toFixed(3),
471
+ populationSize: CONFIG.swarm.populationSize,
472
+ dimensions: CONFIG.swarm.dimensions,
473
+ });
474
+
475
+ // Full optimization run
476
+ const optimizeTimes = [];
477
+ for (let i = 0; i < 10; i++) { // Fewer iterations for full optimization
478
+ const newSwarm = plugin.createSwarm(`bench-opt-${i}`, {
479
+ algorithm,
480
+ dimensions: CONFIG.swarm.dimensions,
481
+ });
482
+
483
+ const start = performance.now();
484
+ await plugin.optimize(`bench-opt-${i}`, { iterations: 50 });
485
+ optimizeTimes.push(performance.now() - start);
486
+ }
487
+
488
+ const optStats = calculateStats(optimizeTimes);
489
+ results.add('Swarm Intelligence', `${algorithm.toUpperCase()} Full Optimization (50 iter)`, {
490
+ avgTimeMs: optStats.mean.toFixed(2),
491
+ p95Ms: optStats.p95.toFixed(2),
492
+ totalIterationsPerSec: formatNumber((50 * 1000) / optStats.mean),
493
+ });
494
+ }
495
+
496
+ // Particle scaling test
497
+ console.log('Testing particle scaling...');
498
+ const scalingSizes = [10, 50, 100, 200, 500];
499
+ const scalingResults = {};
500
+
501
+ for (const popSize of scalingSizes) {
502
+ const plugin = new SwarmIntelligencePlugin({
503
+ algorithm: 'pso',
504
+ populationSize: popSize,
505
+ dimensions: CONFIG.swarm.dimensions,
506
+ });
507
+
508
+ const swarm = plugin.createSwarm('scale-test');
509
+ const times = [];
510
+
511
+ for (let i = 0; i < 50; i++) {
512
+ const start = performance.now();
513
+ plugin.step('scale-test');
514
+ times.push(performance.now() - start);
515
+ }
516
+
517
+ const stats = calculateStats(times);
518
+ scalingResults[popSize] = {
519
+ avgTimeMs: stats.mean.toFixed(3),
520
+ iterPerSec: formatNumber(1000 / stats.mean),
521
+ };
522
+ }
523
+
524
+ results.add('Swarm Intelligence', 'PSO Population Scaling', scalingResults);
525
+ console.log(' Swarm intelligence benchmarks complete');
526
+ }
527
+
528
+ // ============================================
529
+ // FEDERATED LEARNING PLUGIN BENCHMARKS
530
+ // ============================================
531
+
532
+ async function benchmarkFederatedLearning(results) {
533
+ console.log('\n--- FederatedLearningPlugin Performance ---\n');
534
+
535
+ const plugin = new FederatedLearningPlugin({
536
+ aggregationStrategy: 'fedavg',
537
+ localEpochs: CONFIG.federated.epochs,
538
+ differentialPrivacy: true,
539
+ minParticipants: 1, // Allow single participant for benchmarking
540
+ });
541
+
542
+ // Generate test data
543
+ const localData = Array(CONFIG.federated.localDataSize).fill(null).map(() => ({
544
+ features: Array(10).fill(0).map(() => Math.random()),
545
+ label: Math.random() > 0.5 ? 1 : 0,
546
+ }));
547
+
548
+ const globalWeights = Array(10).fill(0).map(() => Math.random());
549
+
550
+ // Local training performance
551
+ console.log('Testing local training...');
552
+ const trainTimes = [];
553
+
554
+ for (let i = 0; i < 50; i++) {
555
+ const roundId = plugin.startRound(`model-${i}`, globalWeights);
556
+
557
+ const start = performance.now();
558
+ await plugin.trainLocal(roundId, localData, {
559
+ participantId: `participant-${i}`,
560
+ epochs: CONFIG.federated.epochs,
561
+ });
562
+ trainTimes.push(performance.now() - start);
563
+ }
564
+
565
+ const trainStats = calculateStats(trainTimes);
566
+ results.add('Federated Learning', 'Local Training', {
567
+ avgTimeMs: trainStats.mean.toFixed(2),
568
+ p95Ms: trainStats.p95.toFixed(2),
569
+ samplesProcessed: CONFIG.federated.localDataSize,
570
+ epochs: CONFIG.federated.epochs,
571
+ samplesPerSecond: formatNumber((CONFIG.federated.localDataSize * CONFIG.federated.epochs * 1000) / trainStats.mean),
572
+ });
573
+
574
+ // Aggregation performance (FedAvg)
575
+ console.log('Testing aggregation...');
576
+ const aggregationTimes = [];
577
+
578
+ for (let i = 0; i < CONFIG.benchmarkIterations; i++) {
579
+ // Simulate multiple participant updates
580
+ const updates = Array(CONFIG.federated.participants).fill(null).map(() => ({
581
+ update: Array(10).fill(0).map(() => Math.random()),
582
+ dataSize: Math.floor(Math.random() * 1000) + 100,
583
+ }));
584
+
585
+ const start = performance.now();
586
+ plugin._fedAvg(updates);
587
+ aggregationTimes.push(performance.now() - start);
588
+ }
589
+
590
+ const aggStats = calculateStats(aggregationTimes);
591
+ results.add('Federated Learning', 'FedAvg Aggregation', {
592
+ avgTimeMs: aggStats.mean.toFixed(4),
593
+ p95Ms: aggStats.p95.toFixed(4),
594
+ opsPerSec: formatNumber(1000 / aggStats.mean),
595
+ participants: CONFIG.federated.participants,
596
+ });
597
+
598
+ // Differential privacy overhead
599
+ console.log('Testing differential privacy overhead...');
600
+ const dpTimes = [];
601
+ const noDpTimes = [];
602
+
603
+ for (let i = 0; i < CONFIG.benchmarkIterations; i++) {
604
+ const weights = Array(100).fill(0).map(() => Math.random());
605
+
606
+ const start1 = performance.now();
607
+ plugin._addDifferentialPrivacy([...weights]);
608
+ dpTimes.push(performance.now() - start1);
609
+
610
+ // Baseline (no DP)
611
+ const start2 = performance.now();
612
+ const _ = weights.map(w => w); // Just copy
613
+ noDpTimes.push(performance.now() - start2);
614
+ }
615
+
616
+ const dpStats = calculateStats(dpTimes);
617
+ const noDpStats = calculateStats(noDpTimes);
618
+ results.add('Federated Learning', 'Differential Privacy Overhead', {
619
+ withDpMs: dpStats.mean.toFixed(4),
620
+ withoutDpMs: noDpStats.mean.toFixed(4),
621
+ overheadFactor: (dpStats.mean / noDpStats.mean).toFixed(2),
622
+ });
623
+
624
+ console.log(' Federated learning benchmarks complete');
625
+ }
626
+
627
+ // ============================================
628
+ // REPUTATION STAKING PLUGIN BENCHMARKS
629
+ // ============================================
630
+
631
+ async function benchmarkReputationStaking(results) {
632
+ console.log('\n--- ReputationStakingPlugin Performance ---\n');
633
+
634
+ const plugin = new ReputationStakingPlugin();
635
+
636
+ // Mock credit system
637
+ const balances = new Map();
638
+ const creditSystem = {
639
+ getBalance: (nodeId) => balances.get(nodeId) || 0,
640
+ spendCredits: (nodeId, amount) => {
641
+ balances.set(nodeId, (balances.get(nodeId) || 0) - amount);
642
+ },
643
+ earnCredits: (nodeId, amount) => {
644
+ balances.set(nodeId, (balances.get(nodeId) || 0) + amount);
645
+ },
646
+ };
647
+
648
+ // Initialize nodes with credits
649
+ for (let i = 0; i < 100; i++) {
650
+ balances.set(`node-${i}`, 10000);
651
+ }
652
+
653
+ // Stake operations
654
+ console.log('Testing stake operations...');
655
+ const stakeTimes = [];
656
+ for (let i = 0; i < CONFIG.staking.operations; i++) {
657
+ const nodeId = `node-${i % 100}`;
658
+ const start = performance.now();
659
+ try {
660
+ plugin.stake(nodeId, 100, creditSystem);
661
+ } catch (e) {
662
+ // Ignore insufficient balance
663
+ }
664
+ stakeTimes.push(performance.now() - start);
665
+ }
666
+
667
+ const stakeStats = calculateStats(stakeTimes);
668
+ results.add('Reputation Staking', 'Stake Operations', {
669
+ opsPerSec: formatNumber(1000 / stakeStats.mean),
670
+ avgTimeMs: stakeStats.mean.toFixed(4),
671
+ p95Ms: stakeStats.p95.toFixed(4),
672
+ });
673
+
674
+ // Slash operations
675
+ console.log('Testing slash operations...');
676
+ const slashTimes = [];
677
+ for (let i = 0; i < CONFIG.staking.operations; i++) {
678
+ const nodeId = `node-${i % 100}`;
679
+ const start = performance.now();
680
+ plugin.slash(nodeId, 'benchmark-test', 0.5);
681
+ slashTimes.push(performance.now() - start);
682
+ }
683
+
684
+ const slashStats = calculateStats(slashTimes);
685
+ results.add('Reputation Staking', 'Slash Operations', {
686
+ opsPerSec: formatNumber(1000 / slashStats.mean),
687
+ avgTimeMs: slashStats.mean.toFixed(4),
688
+ p95Ms: slashStats.p95.toFixed(4),
689
+ });
690
+
691
+ // Reputation checks
692
+ console.log('Testing reputation lookups...');
693
+ const reputationTimes = [];
694
+ for (let i = 0; i < CONFIG.staking.operations; i++) {
695
+ const nodeId = `node-${i % 100}`;
696
+ const start = performance.now();
697
+ plugin.getReputation(nodeId);
698
+ reputationTimes.push(performance.now() - start);
699
+ }
700
+
701
+ const repStats = calculateStats(reputationTimes);
702
+ results.add('Reputation Staking', 'Reputation Lookups', {
703
+ opsPerSec: formatNumber(1000 / repStats.mean),
704
+ avgTimeMs: repStats.mean.toFixed(5),
705
+ p95Ms: repStats.p95.toFixed(5),
706
+ });
707
+
708
+ // Leaderboard computation
709
+ console.log('Testing leaderboard computation...');
710
+ const leaderboardTimes = [];
711
+ for (let i = 0; i < 100; i++) {
712
+ const start = performance.now();
713
+ plugin.getLeaderboard(10);
714
+ leaderboardTimes.push(performance.now() - start);
715
+ }
716
+
717
+ const lbStats = calculateStats(leaderboardTimes);
718
+ results.add('Reputation Staking', 'Leaderboard (top 10)', {
719
+ opsPerSec: formatNumber(1000 / lbStats.mean),
720
+ avgTimeMs: lbStats.mean.toFixed(3),
721
+ p95Ms: lbStats.p95.toFixed(3),
722
+ stakerCount: plugin.stakes.size,
723
+ });
724
+
725
+ // Eligibility checks
726
+ console.log('Testing eligibility checks...');
727
+ const eligibilityTimes = [];
728
+ for (let i = 0; i < CONFIG.staking.operations; i++) {
729
+ const nodeId = `node-${i % 100}`;
730
+ const start = performance.now();
731
+ plugin.isEligible(nodeId, 50, 100);
732
+ eligibilityTimes.push(performance.now() - start);
733
+ }
734
+
735
+ const eligStats = calculateStats(eligibilityTimes);
736
+ results.add('Reputation Staking', 'Eligibility Checks', {
737
+ opsPerSec: formatNumber(1000 / eligStats.mean),
738
+ avgTimeMs: eligStats.mean.toFixed(5),
739
+ p95Ms: eligStats.p95.toFixed(5),
740
+ });
741
+
742
+ console.log(' Reputation staking benchmarks complete');
743
+ }
744
+
745
+ // ============================================
746
+ // SANDBOX OVERHEAD BENCHMARKS
747
+ // ============================================
748
+
749
+ async function benchmarkSandboxOverhead(results) {
750
+ console.log('\n--- Sandbox Overhead ---\n');
751
+
752
+ const loader = new PluginLoader({ verifySignatures: false });
753
+
754
+ // Capability check overhead
755
+ console.log('Testing capability check overhead...');
756
+ const sandbox = loader._createSandbox(['NETWORK_CONNECT', 'CRYPTO_ENCRYPT']);
757
+
758
+ const capCheckTimes = [];
759
+ for (let i = 0; i < CONFIG.benchmarkIterations * 10; i++) {
760
+ const start = performance.now();
761
+ sandbox.hasCapability('NETWORK_CONNECT');
762
+ capCheckTimes.push(performance.now() - start);
763
+ }
764
+
765
+ const capStats = calculateStats(capCheckTimes);
766
+ results.add('Sandbox Overhead', 'Capability Check', {
767
+ opsPerSec: formatNumber(1000 / capStats.mean),
768
+ avgTimeNs: (capStats.mean * 1000000).toFixed(0),
769
+ p95Ns: (capStats.p95 * 1000000).toFixed(0),
770
+ });
771
+
772
+ // API call overhead vs direct
773
+ console.log('Testing API call overhead...');
774
+
775
+ // Direct function call baseline
776
+ const directTimes = [];
777
+ const directFn = (x) => x * 2;
778
+ for (let i = 0; i < CONFIG.benchmarkIterations * 10; i++) {
779
+ const start = performance.now();
780
+ directFn(i);
781
+ directTimes.push(performance.now() - start);
782
+ }
783
+
784
+ // Sandboxed API call
785
+ const api = loader._createPluginAPI({ capabilities: ['CRYPTO_ENCRYPT'] }, sandbox);
786
+ const sandboxedTimes = [];
787
+ for (let i = 0; i < CONFIG.benchmarkIterations * 10; i++) {
788
+ const start = performance.now();
789
+ sandbox.hasCapability('CRYPTO_ENCRYPT');
790
+ // Simulate API work
791
+ const _ = i * 2;
792
+ sandboxedTimes.push(performance.now() - start);
793
+ }
794
+
795
+ const directStats = calculateStats(directTimes);
796
+ const sandboxedStats = calculateStats(sandboxedTimes);
797
+
798
+ results.add('Sandbox Overhead', 'Direct vs Sandboxed Call', {
799
+ directAvgNs: (directStats.mean * 1000000).toFixed(0),
800
+ sandboxedAvgNs: (sandboxedStats.mean * 1000000).toFixed(0),
801
+ overheadFactor: (sandboxedStats.mean / directStats.mean).toFixed(2),
802
+ overheadNs: ((sandboxedStats.mean - directStats.mean) * 1000000).toFixed(0),
803
+ });
804
+
805
+ // Capability require (with exception path)
806
+ console.log('Testing capability require overhead...');
807
+ const requireTimes = [];
808
+ for (let i = 0; i < CONFIG.benchmarkIterations * 10; i++) {
809
+ const start = performance.now();
810
+ sandbox.require('NETWORK_CONNECT');
811
+ requireTimes.push(performance.now() - start);
812
+ }
813
+
814
+ const requireStats = calculateStats(requireTimes);
815
+ results.add('Sandbox Overhead', 'Capability Require', {
816
+ opsPerSec: formatNumber(1000 / requireStats.mean),
817
+ avgTimeNs: (requireStats.mean * 1000000).toFixed(0),
818
+ });
819
+
820
+ console.log(' Sandbox overhead benchmarks complete');
821
+ }
822
+
823
+ // ============================================
824
+ // MEMORY USAGE BENCHMARKS
825
+ // ============================================
826
+
827
+ async function benchmarkMemoryUsage(results) {
828
+ console.log('\n--- Memory Usage ---\n');
829
+
830
+ // Force GC if available
831
+ if (global.gc) {
832
+ global.gc();
833
+ }
834
+
835
+ const baseMemory = getMemoryUsage();
836
+
837
+ // Base memory footprint (no plugins)
838
+ results.add('Memory Usage', 'Base Memory', {
839
+ heapUsed: formatBytes(baseMemory.heapUsed),
840
+ heapTotal: formatBytes(baseMemory.heapTotal),
841
+ rss: formatBytes(baseMemory.rss),
842
+ });
843
+
844
+ // Per-plugin memory cost
845
+ console.log('Measuring per-plugin memory...');
846
+ const pluginMemory = {};
847
+
848
+ const plugins = [
849
+ { name: 'Compression', factory: () => new CompressionPlugin() },
850
+ { name: 'E2E Encryption', factory: () => new E2EEncryptionPlugin() },
851
+ { name: 'Swarm Intelligence', factory: () => new SwarmIntelligencePlugin() },
852
+ { name: 'Federated Learning', factory: () => new FederatedLearningPlugin() },
853
+ { name: 'Reputation Staking', factory: () => new ReputationStakingPlugin() },
854
+ ];
855
+
856
+ for (const { name, factory } of plugins) {
857
+ global.gc?.();
858
+ const before = getMemoryUsage();
859
+
860
+ const instances = [];
861
+ for (let i = 0; i < 10; i++) {
862
+ instances.push(factory());
863
+ }
864
+
865
+ global.gc?.();
866
+ const after = getMemoryUsage();
867
+
868
+ pluginMemory[name] = {
869
+ perInstance: formatBytes((after.heapUsed - before.heapUsed) / 10),
870
+ perInstanceBytes: Math.floor((after.heapUsed - before.heapUsed) / 10),
871
+ };
872
+ }
873
+
874
+ results.add('Memory Usage', 'Per-Plugin Memory', pluginMemory);
875
+
876
+ // Memory after 1000 operations
877
+ console.log('Measuring memory after sustained operations...');
878
+
879
+ global.gc?.();
880
+ const beforeOps = getMemoryUsage();
881
+
882
+ // Compression operations
883
+ const compression = new CompressionPlugin({ threshold: 0 });
884
+ for (let i = 0; i < CONFIG.memoryOperations; i++) {
885
+ const data = generateCompressibleData(1024);
886
+ const compressed = compression.compress(data);
887
+ compression.decompress(compressed.data, compressed.compressed);
888
+ }
889
+
890
+ // Encryption operations
891
+ const encryption = new E2EEncryptionPlugin({ forwardSecrecy: false });
892
+ for (let i = 0; i < CONFIG.memoryOperations; i++) {
893
+ await encryption.establishSession(`peer-${i}`, 'key');
894
+ encryption.encrypt(`peer-${i}`, 'test message');
895
+ }
896
+
897
+ // Swarm operations
898
+ const swarm = new SwarmIntelligencePlugin();
899
+ for (let i = 0; i < Math.min(100, CONFIG.memoryOperations); i++) {
900
+ swarm.createSwarm(`swarm-${i}`);
901
+ for (let j = 0; j < 10; j++) {
902
+ swarm.step(`swarm-${i}`);
903
+ }
904
+ }
905
+
906
+ global.gc?.();
907
+ const afterOps = getMemoryUsage();
908
+
909
+ results.add('Memory Usage', 'After 1000 Operations', {
910
+ heapGrowth: formatBytes(afterOps.heapUsed - beforeOps.heapUsed),
911
+ heapGrowthBytes: afterOps.heapUsed - beforeOps.heapUsed,
912
+ finalHeap: formatBytes(afterOps.heapUsed),
913
+ operationsPerMB: Math.floor(CONFIG.memoryOperations / ((afterOps.heapUsed - beforeOps.heapUsed) / 1048576)),
914
+ });
915
+
916
+ // Memory pressure test (create and release)
917
+ console.log('Testing memory release...');
918
+
919
+ global.gc?.();
920
+ const beforePressure = getMemoryUsage();
921
+
922
+ // Create many instances
923
+ const instances = [];
924
+ for (let i = 0; i < 100; i++) {
925
+ instances.push(new CompressionPlugin());
926
+ instances.push(new E2EEncryptionPlugin());
927
+ instances.push(new SwarmIntelligencePlugin());
928
+ }
929
+
930
+ global.gc?.();
931
+ const peakMemory = getMemoryUsage();
932
+
933
+ // Release
934
+ instances.length = 0;
935
+ global.gc?.();
936
+ const releasedMemory = getMemoryUsage();
937
+
938
+ results.add('Memory Usage', 'Memory Pressure Test', {
939
+ peakGrowth: formatBytes(peakMemory.heapUsed - beforePressure.heapUsed),
940
+ afterRelease: formatBytes(releasedMemory.heapUsed - beforePressure.heapUsed),
941
+ releaseEfficiency: ((1 - (releasedMemory.heapUsed - beforePressure.heapUsed) /
942
+ (peakMemory.heapUsed - beforePressure.heapUsed)) * 100).toFixed(1) + '%',
943
+ });
944
+
945
+ console.log(' Memory usage benchmarks complete');
946
+ }
947
+
948
+ // ============================================
949
+ // BASELINE COMPARISON
950
+ // ============================================
951
+
952
+ async function benchmarkBaseline(results) {
953
+ console.log('\n--- Baseline Comparison (No Plugins) ---\n');
954
+
955
+ // Direct operations without plugin overhead
956
+
957
+ // Raw buffer operations (baseline for compression)
958
+ console.log('Testing raw buffer operations...');
959
+ const rawBufferTimes = [];
960
+ for (let i = 0; i < CONFIG.benchmarkIterations; i++) {
961
+ const data = Buffer.alloc(65536);
962
+ const start = performance.now();
963
+ const copy = Buffer.from(data);
964
+ rawBufferTimes.push(performance.now() - start);
965
+ }
966
+
967
+ results.add('Baseline', 'Raw Buffer Copy (64KB)', {
968
+ avgTimeMs: calculateStats(rawBufferTimes).mean.toFixed(4),
969
+ throughputMBs: ((65536 / 1048576) / (calculateStats(rawBufferTimes).mean / 1000)).toFixed(2),
970
+ });
971
+
972
+ // Raw crypto operations (baseline for encryption)
973
+ console.log('Testing raw crypto operations...');
974
+ const { createCipheriv, randomBytes, createHash } = await import('crypto');
975
+
976
+ const cryptoTimes = [];
977
+ const key = randomBytes(32);
978
+ const testData = randomBytes(1024);
979
+
980
+ for (let i = 0; i < CONFIG.benchmarkIterations; i++) {
981
+ const iv = randomBytes(12);
982
+ const start = performance.now();
983
+ const cipher = createCipheriv('aes-256-gcm', key, iv);
984
+ cipher.update(testData);
985
+ cipher.final();
986
+ cipher.getAuthTag();
987
+ cryptoTimes.push(performance.now() - start);
988
+ }
989
+
990
+ results.add('Baseline', 'Raw AES-256-GCM (1KB)', {
991
+ avgTimeMs: calculateStats(cryptoTimes).mean.toFixed(4),
992
+ opsPerSec: formatNumber(1000 / calculateStats(cryptoTimes).mean),
993
+ });
994
+
995
+ // Map operations (baseline for staking)
996
+ console.log('Testing raw Map operations...');
997
+ const map = new Map();
998
+ const mapTimes = [];
999
+
1000
+ for (let i = 0; i < CONFIG.staking.operations; i++) {
1001
+ const start = performance.now();
1002
+ map.set(`key-${i}`, { value: i, data: { nested: true } });
1003
+ map.get(`key-${i % (i + 1)}`);
1004
+ mapTimes.push(performance.now() - start);
1005
+ }
1006
+
1007
+ results.add('Baseline', 'Raw Map Operations', {
1008
+ avgTimeNs: (calculateStats(mapTimes).mean * 1000000).toFixed(0),
1009
+ opsPerSec: formatNumber(1000 / calculateStats(mapTimes).mean),
1010
+ });
1011
+
1012
+ // Math operations (baseline for swarm)
1013
+ console.log('Testing raw math operations...');
1014
+ const mathTimes = [];
1015
+ const dimensions = CONFIG.swarm.dimensions;
1016
+ const particles = CONFIG.swarm.populationSize;
1017
+
1018
+ for (let i = 0; i < CONFIG.benchmarkIterations; i++) {
1019
+ const start = performance.now();
1020
+ for (let p = 0; p < particles; p++) {
1021
+ let sum = 0;
1022
+ for (let d = 0; d < dimensions; d++) {
1023
+ sum += Math.random() * Math.random() + Math.sqrt(Math.random());
1024
+ }
1025
+ }
1026
+ mathTimes.push(performance.now() - start);
1027
+ }
1028
+
1029
+ results.add('Baseline', 'Raw Math Operations (50 particles x 10 dim)', {
1030
+ avgTimeMs: calculateStats(mathTimes).mean.toFixed(3),
1031
+ opsPerSec: formatNumber(1000 / calculateStats(mathTimes).mean),
1032
+ });
1033
+
1034
+ console.log(' Baseline benchmarks complete');
1035
+ }
1036
+
1037
+ // ============================================
1038
+ // REPORT GENERATION
1039
+ // ============================================
1040
+
1041
+ function generateTextReport(report) {
1042
+ const lines = [];
1043
+
1044
+ lines.push('');
1045
+ lines.push('='.repeat(80));
1046
+ lines.push(' EDGE-NET PLUGIN SYSTEM PERFORMANCE BENCHMARKS');
1047
+ lines.push('='.repeat(80));
1048
+ lines.push('');
1049
+ lines.push(`Timestamp: ${report.timestamp}`);
1050
+ lines.push(`Duration: ${(report.duration / 1000).toFixed(2)}s`);
1051
+ lines.push(`Node.js: ${report.nodeVersion}`);
1052
+ lines.push(`Platform: ${report.platform} (${report.arch})`);
1053
+ lines.push('');
1054
+
1055
+ for (const [category, metrics] of Object.entries(report.categories)) {
1056
+ lines.push('-'.repeat(80));
1057
+ lines.push(` ${category}`);
1058
+ lines.push('-'.repeat(80));
1059
+ lines.push('');
1060
+
1061
+ for (const [name, data] of Object.entries(metrics)) {
1062
+ if (typeof data === 'object' && !Array.isArray(data)) {
1063
+ lines.push(` ${name}:`);
1064
+ for (const [key, value] of Object.entries(data)) {
1065
+ if (typeof value === 'object') {
1066
+ lines.push(` ${key}: ${JSON.stringify(value)}`);
1067
+ } else {
1068
+ lines.push(` ${key}: ${value}`);
1069
+ }
1070
+ }
1071
+ } else {
1072
+ lines.push(` ${name}: ${JSON.stringify(data)}`);
1073
+ }
1074
+ lines.push('');
1075
+ }
1076
+ }
1077
+
1078
+ lines.push('='.repeat(80));
1079
+ lines.push(' SUMMARY & RECOMMENDATIONS');
1080
+ lines.push('='.repeat(80));
1081
+ lines.push('');
1082
+
1083
+ // Extract key metrics for summary
1084
+ const compressionThroughput = report.categories['Compression']?.['medium Compress (compressible)']?.throughputMBs || 'N/A';
1085
+ const encryptionOps = report.categories['Encryption']?.['small Encrypt']?.opsPerSec || 'N/A';
1086
+ const swarmIterSec = report.categories['Swarm Intelligence']?.['PSO Step']?.iterationsPerSec || 'N/A';
1087
+ const stakingOps = report.categories['Reputation Staking']?.['Stake Operations']?.opsPerSec || 'N/A';
1088
+ const sandboxOverhead = report.categories['Sandbox Overhead']?.['Direct vs Sandboxed Call']?.overheadFactor || 'N/A';
1089
+
1090
+ lines.push('Key Performance Metrics:');
1091
+ lines.push(` - Compression throughput: ${compressionThroughput} MB/s`);
1092
+ lines.push(` - Encryption operations: ${encryptionOps} ops/sec`);
1093
+ lines.push(` - Swarm PSO iterations: ${swarmIterSec} iter/sec`);
1094
+ lines.push(` - Staking operations: ${stakingOps} ops/sec`);
1095
+ lines.push(` - Sandbox overhead factor: ${sandboxOverhead}x`);
1096
+ lines.push('');
1097
+
1098
+ lines.push('Optimization Recommendations:');
1099
+ lines.push('');
1100
+
1101
+ // Provide context-aware recommendations
1102
+ const compressionNum = parseFloat(compressionThroughput) || 0;
1103
+ if (compressionNum < 100) {
1104
+ lines.push(' [!] Compression: Consider using native WASM LZ4 for better throughput');
1105
+ } else {
1106
+ lines.push(' [OK] Compression: Throughput is acceptable for most use cases');
1107
+ }
1108
+
1109
+ const sandboxNum = parseFloat(sandboxOverhead) || 0;
1110
+ if (sandboxNum > 5) {
1111
+ lines.push(' [!] Sandbox: High overhead detected - consider caching capability checks');
1112
+ } else {
1113
+ lines.push(' [OK] Sandbox: Overhead is within acceptable range');
1114
+ }
1115
+
1116
+ lines.push('');
1117
+ lines.push('For production deployments:');
1118
+ lines.push(' 1. Enable WASM SIMD for compression/encryption acceleration');
1119
+ lines.push(' 2. Use worker threads for swarm intelligence computations');
1120
+ lines.push(' 3. Consider batching staking operations for high-throughput scenarios');
1121
+ lines.push(' 4. Monitor memory usage with --expose-gc for accurate measurements');
1122
+ lines.push('');
1123
+
1124
+ return lines.join('\n');
1125
+ }
1126
+
1127
+ function generateSummaryTable(report) {
1128
+ const lines = [];
1129
+
1130
+ lines.push('');
1131
+ lines.push('+' + '-'.repeat(78) + '+');
1132
+ lines.push('|' + ' '.repeat(25) + 'PERFORMANCE SUMMARY TABLE' + ' '.repeat(28) + '|');
1133
+ lines.push('+' + '-'.repeat(78) + '+');
1134
+ lines.push('| Plugin/Operation | Metric | Value | Unit |');
1135
+ lines.push('+' + '-'.repeat(78) + '+');
1136
+
1137
+ const tableRows = [
1138
+ // Compression
1139
+ { plugin: 'CompressionPlugin', op: 'Compress (64KB)', metric: 'Throughput', value: report.categories['Compression']?.['medium Compress (compressible)']?.throughputMBs || 'N/A', unit: 'MB/s' },
1140
+ { plugin: 'CompressionPlugin', op: 'Decompress (64KB)', metric: 'Throughput', value: report.categories['Compression']?.['medium Decompress']?.throughputMBs || 'N/A', unit: 'MB/s' },
1141
+
1142
+ // Encryption
1143
+ { plugin: 'E2EEncryptionPlugin', op: 'Encrypt (1KB)', metric: 'Operations', value: report.categories['Encryption']?.['small Encrypt']?.opsPerSec || 'N/A', unit: 'ops/sec' },
1144
+ { plugin: 'E2EEncryptionPlugin', op: 'Decrypt (1KB)', metric: 'Operations', value: report.categories['Encryption']?.['small Decrypt']?.opsPerSec || 'N/A', unit: 'ops/sec' },
1145
+ { plugin: 'E2EEncryptionPlugin', op: 'Session Setup', metric: 'Operations', value: report.categories['Encryption']?.['Session Establishment']?.opsPerSec || 'N/A', unit: 'ops/sec' },
1146
+
1147
+ // Swarm Intelligence
1148
+ { plugin: 'SwarmIntelligencePlugin', op: 'PSO Step', metric: 'Iterations', value: report.categories['Swarm Intelligence']?.['PSO Step']?.iterationsPerSec || 'N/A', unit: 'iter/sec' },
1149
+ { plugin: 'SwarmIntelligencePlugin', op: 'GA Step', metric: 'Iterations', value: report.categories['Swarm Intelligence']?.['GA Step']?.iterationsPerSec || 'N/A', unit: 'iter/sec' },
1150
+ { plugin: 'SwarmIntelligencePlugin', op: 'DE Step', metric: 'Iterations', value: report.categories['Swarm Intelligence']?.['DE Step']?.iterationsPerSec || 'N/A', unit: 'iter/sec' },
1151
+
1152
+ // Federated Learning
1153
+ { plugin: 'FederatedLearningPlugin', op: 'Local Training', metric: 'Samples', value: report.categories['Federated Learning']?.['Local Training']?.samplesPerSecond || 'N/A', unit: 'samples/s' },
1154
+ { plugin: 'FederatedLearningPlugin', op: 'FedAvg', metric: 'Aggregations', value: report.categories['Federated Learning']?.['FedAvg Aggregation']?.opsPerSec || 'N/A', unit: 'ops/sec' },
1155
+
1156
+ // Reputation Staking
1157
+ { plugin: 'ReputationStakingPlugin', op: 'Stake', metric: 'Operations', value: report.categories['Reputation Staking']?.['Stake Operations']?.opsPerSec || 'N/A', unit: 'ops/sec' },
1158
+ { plugin: 'ReputationStakingPlugin', op: 'Slash', metric: 'Operations', value: report.categories['Reputation Staking']?.['Slash Operations']?.opsPerSec || 'N/A', unit: 'ops/sec' },
1159
+ { plugin: 'ReputationStakingPlugin', op: 'Reputation Lookup', metric: 'Operations', value: report.categories['Reputation Staking']?.['Reputation Lookups']?.opsPerSec || 'N/A', unit: 'ops/sec' },
1160
+
1161
+ // Sandbox
1162
+ { plugin: 'Sandbox', op: 'Capability Check', metric: 'Operations', value: report.categories['Sandbox Overhead']?.['Capability Check']?.opsPerSec || 'N/A', unit: 'ops/sec' },
1163
+ { plugin: 'Sandbox', op: 'Overhead Factor', metric: 'Factor', value: report.categories['Sandbox Overhead']?.['Direct vs Sandboxed Call']?.overheadFactor || 'N/A', unit: 'x' },
1164
+ ];
1165
+
1166
+ for (const row of tableRows) {
1167
+ const pluginPad = (row.plugin + ' ' + row.op).substring(0, 30).padEnd(30);
1168
+ const metricPad = row.metric.padEnd(20);
1169
+ const valuePad = String(row.value).padEnd(17);
1170
+ const unitPad = row.unit.padEnd(9);
1171
+ lines.push(`| ${pluginPad}| ${metricPad}| ${valuePad}| ${unitPad}|`);
1172
+ }
1173
+
1174
+ lines.push('+' + '-'.repeat(78) + '+');
1175
+ lines.push('');
1176
+
1177
+ return lines.join('\n');
1178
+ }
1179
+
1180
+ // ============================================
1181
+ // MAIN BENCHMARK RUNNER
1182
+ // ============================================
1183
+
1184
+ async function runBenchmarks() {
1185
+ console.log('');
1186
+ console.log('='.repeat(60));
1187
+ console.log(' Edge-Net Plugin System Performance Benchmarks');
1188
+ console.log('='.repeat(60));
1189
+ console.log('');
1190
+ console.log('Configuration:');
1191
+ console.log(` - Warmup iterations: ${CONFIG.warmupIterations}`);
1192
+ console.log(` - Benchmark iterations: ${CONFIG.benchmarkIterations}`);
1193
+ console.log(` - Data sizes: ${Object.entries(CONFIG.dataSizes).map(([k, v]) => `${k}=${formatBytes(v)}`).join(', ')}`);
1194
+ console.log(` - GC available: ${typeof global.gc === 'function' ? 'Yes' : 'No (run with --expose-gc for accurate memory)'}`);
1195
+ console.log('');
1196
+
1197
+ const results = new BenchmarkResults();
1198
+
1199
+ try {
1200
+ // Run all benchmarks
1201
+ await benchmarkPluginLoading(results);
1202
+ await benchmarkCompression(results);
1203
+ await benchmarkEncryption(results);
1204
+ await benchmarkSwarmIntelligence(results);
1205
+ await benchmarkFederatedLearning(results);
1206
+ await benchmarkReputationStaking(results);
1207
+ await benchmarkSandboxOverhead(results);
1208
+ await benchmarkMemoryUsage(results);
1209
+ await benchmarkBaseline(results);
1210
+
1211
+ // Generate reports
1212
+ const report = results.generateReport();
1213
+
1214
+ console.log(generateSummaryTable(report));
1215
+ console.log(generateTextReport(report));
1216
+
1217
+ // Output JSON for programmatic access
1218
+ console.log('\n--- JSON Output ---\n');
1219
+ console.log(JSON.stringify(report, null, 2));
1220
+
1221
+ return report;
1222
+
1223
+ } catch (error) {
1224
+ console.error('\nBenchmark failed:', error);
1225
+ console.error(error.stack);
1226
+ process.exit(1);
1227
+ }
1228
+ }
1229
+
1230
+ // Run if executed directly
1231
+ runBenchmarks().then(() => {
1232
+ console.log('\nBenchmarks completed successfully.');
1233
+ process.exit(0);
1234
+ }).catch((error) => {
1235
+ console.error('Fatal error:', error);
1236
+ process.exit(1);
1237
+ });
1238
+
1239
+ export { runBenchmarks, CONFIG };