597 lines
18 KiB
JavaScript
597 lines
18 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Strange Loops Comprehensive Benchmark Suite
|
|
*
|
|
* Measures performance characteristics of various strange loop implementations:
|
|
* - Execution time
|
|
* - Memory consumption
|
|
* - Recursion depth impact
|
|
* - Cache efficiency
|
|
* - Scalability
|
|
* - Resource utilization
|
|
*/
|
|
|
|
import { performance } from 'perf_hooks';
|
|
import { createWriteStream } from 'fs';
|
|
import { join, dirname } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
import os from 'os';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
|
|
// ============================================================================
|
|
// Benchmark Framework
|
|
// ============================================================================
|
|
|
|
class BenchmarkSuite {
|
|
constructor(name) {
|
|
this.name = name;
|
|
this.results = [];
|
|
this.startTime = null;
|
|
this.systemInfo = {
|
|
platform: os.platform(),
|
|
arch: os.arch(),
|
|
cpus: os.cpus().length,
|
|
memory: os.totalmem(),
|
|
nodeVersion: process.version
|
|
};
|
|
}
|
|
|
|
async warmup(fn, iterations = 100) {
|
|
console.log(` ๐ฅ Warming up ${iterations} iterations...`);
|
|
for (let i = 0; i < iterations; i++) {
|
|
await fn();
|
|
}
|
|
}
|
|
|
|
async measure(name, fn, options = {}) {
|
|
const {
|
|
iterations = 1000,
|
|
warmupIterations = 100,
|
|
collectGarbage = true
|
|
} = options;
|
|
|
|
// Warmup phase
|
|
if (warmupIterations > 0) {
|
|
await this.warmup(fn, warmupIterations);
|
|
}
|
|
|
|
// Force garbage collection if available
|
|
if (collectGarbage && global.gc) {
|
|
global.gc();
|
|
}
|
|
|
|
const measurements = {
|
|
times: [],
|
|
memory: [],
|
|
iterations
|
|
};
|
|
|
|
// Measurement phase
|
|
console.log(` ๐ Measuring ${name} (${iterations} iterations)...`);
|
|
|
|
for (let i = 0; i < iterations; i++) {
|
|
const memBefore = process.memoryUsage();
|
|
const startTime = performance.now();
|
|
|
|
await fn();
|
|
|
|
const endTime = performance.now();
|
|
const memAfter = process.memoryUsage();
|
|
|
|
measurements.times.push(endTime - startTime);
|
|
measurements.memory.push({
|
|
heapUsed: memAfter.heapUsed - memBefore.heapUsed,
|
|
external: memAfter.external - memBefore.external
|
|
});
|
|
|
|
// Progress indicator
|
|
if (i % Math.floor(iterations / 10) === 0) {
|
|
process.stdout.write('.');
|
|
}
|
|
}
|
|
process.stdout.write('\n');
|
|
|
|
// Calculate statistics
|
|
const stats = this.calculateStats(measurements);
|
|
this.results.push({ name, ...stats });
|
|
|
|
return stats;
|
|
}
|
|
|
|
calculateStats(measurements) {
|
|
const times = measurements.times;
|
|
const memory = measurements.memory;
|
|
|
|
// Time statistics
|
|
times.sort((a, b) => a - b);
|
|
const timeStats = {
|
|
min: times[0],
|
|
max: times[times.length - 1],
|
|
mean: times.reduce((a, b) => a + b, 0) / times.length,
|
|
median: times[Math.floor(times.length / 2)],
|
|
p95: times[Math.floor(times.length * 0.95)],
|
|
p99: times[Math.floor(times.length * 0.99)],
|
|
stdDev: this.standardDeviation(times)
|
|
};
|
|
|
|
// Memory statistics
|
|
const heapUsages = memory.map(m => m.heapUsed);
|
|
const memStats = {
|
|
meanHeap: heapUsages.reduce((a, b) => a + b, 0) / heapUsages.length,
|
|
maxHeap: Math.max(...heapUsages),
|
|
minHeap: Math.min(...heapUsages)
|
|
};
|
|
|
|
return {
|
|
iterations: measurements.iterations,
|
|
time: timeStats,
|
|
memory: memStats
|
|
};
|
|
}
|
|
|
|
standardDeviation(values) {
|
|
const mean = values.reduce((a, b) => a + b, 0) / values.length;
|
|
const variance = values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / values.length;
|
|
return Math.sqrt(variance);
|
|
}
|
|
|
|
generateReport() {
|
|
console.log('\n' + '='.repeat(80));
|
|
console.log(`๐ BENCHMARK REPORT: ${this.name}`);
|
|
console.log('='.repeat(80));
|
|
|
|
console.log('\n๐ฑ System Information:');
|
|
console.log(` Platform: ${this.systemInfo.platform} ${this.systemInfo.arch}`);
|
|
console.log(` CPUs: ${this.systemInfo.cpus}`);
|
|
console.log(` Memory: ${(this.systemInfo.memory / 1024 / 1024 / 1024).toFixed(2)} GB`);
|
|
console.log(` Node: ${this.systemInfo.nodeVersion}`);
|
|
|
|
console.log('\n๐ Performance Results:\n');
|
|
|
|
// Sort by mean time
|
|
this.results.sort((a, b) => a.time.mean - b.time.mean);
|
|
|
|
// Print table header
|
|
console.log('โ' + 'โ'.repeat(78) + 'โ');
|
|
console.log('โ Loop Type โ Mean โ P95 โ P99 โ Heap (KB) โ');
|
|
console.log('โ' + 'โ'.repeat(78) + 'โค');
|
|
|
|
// Print results
|
|
for (const result of this.results) {
|
|
const name = result.name.padEnd(28);
|
|
const mean = `${result.time.mean.toFixed(3)}ms`.padStart(7);
|
|
const p95 = `${result.time.p95.toFixed(3)}ms`.padStart(8);
|
|
const p99 = `${result.time.p99.toFixed(3)}ms`.padStart(8);
|
|
const heap = `${(result.memory.meanHeap / 1024).toFixed(1)}`.padStart(11);
|
|
|
|
console.log(`โ ${name} โ ${mean} โ ${p95} โ ${p99} โ ${heap} โ`);
|
|
}
|
|
|
|
console.log('โ' + 'โ'.repeat(78) + 'โ');
|
|
|
|
// Performance comparison
|
|
if (this.results.length > 1) {
|
|
const fastest = this.results[0];
|
|
console.log('\n๐ Performance Rankings:\n');
|
|
|
|
this.results.forEach((result, index) => {
|
|
const relativeSpeed = (result.time.mean / fastest.time.mean).toFixed(2);
|
|
const medal = index === 0 ? '๐ฅ' : index === 1 ? '๐ฅ' : index === 2 ? '๐ฅ' : ' ';
|
|
console.log(`${medal} ${(index + 1 + '.').padEnd(3)} ${result.name.padEnd(30)} ${relativeSpeed}x`);
|
|
});
|
|
}
|
|
|
|
return this.results;
|
|
}
|
|
|
|
exportCSV(filename) {
|
|
const csv = [
|
|
'Name,Iterations,Mean(ms),Median(ms),Min(ms),Max(ms),P95(ms),P99(ms),StdDev(ms),MeanHeap(KB)',
|
|
...this.results.map(r =>
|
|
`${r.name},${r.iterations},${r.time.mean},${r.time.median},${r.time.min},${r.time.max},${r.time.p95},${r.time.p99},${r.time.stdDev},${r.memory.meanHeap / 1024}`
|
|
)
|
|
].join('\n');
|
|
|
|
const filepath = join(__dirname, filename);
|
|
require('fs').writeFileSync(filepath, csv);
|
|
console.log(`\n๐พ Results exported to ${filepath}`);
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// Strange Loop Implementations to Benchmark
|
|
// ============================================================================
|
|
|
|
// 1. Simple Self-Reference
|
|
async function simpleSelfReference(depth = 5) {
|
|
const obj = {
|
|
value: 0,
|
|
ref: null,
|
|
process: function(d = depth) {
|
|
if (d <= 0) return this.value;
|
|
this.value++;
|
|
this.ref = this;
|
|
return this.process(d - 1);
|
|
}
|
|
};
|
|
return obj.process();
|
|
}
|
|
|
|
// 2. Indirect Loop with Memoization
|
|
const memoCache = new Map();
|
|
async function memoizedIndirectLoop(n = 10) {
|
|
if (memoCache.has(n)) return memoCache.get(n);
|
|
|
|
const result = n <= 1 ? n : await memoizedIndirectLoop(n - 1) + await memoizedIndirectLoop(n - 2);
|
|
memoCache.set(n, result);
|
|
return result;
|
|
}
|
|
|
|
// 3. Swarm Self-Modification Simulation
|
|
async function swarmSelfModification(agentCount = 10) {
|
|
const swarm = {
|
|
agents: new Array(agentCount).fill(0).map((_, i) => ({ id: i, fitness: Math.random() })),
|
|
evolve: function() {
|
|
// Remove weak agents
|
|
this.agents = this.agents.filter(a => a.fitness > 0.3);
|
|
// Add new agents
|
|
const newCount = Math.min(5, 20 - this.agents.length);
|
|
for (let i = 0; i < newCount; i++) {
|
|
this.agents.push({ id: Date.now() + i, fitness: Math.random() });
|
|
}
|
|
// Mutate existing
|
|
this.agents.forEach(a => a.fitness *= (0.9 + Math.random() * 0.2));
|
|
return this.agents.length;
|
|
}
|
|
};
|
|
|
|
for (let i = 0; i < 5; i++) {
|
|
swarm.evolve();
|
|
}
|
|
return swarm.agents.length;
|
|
}
|
|
|
|
// 4. Knowledge Graph Recursion
|
|
async function knowledgeGraphRecursion(depth = 5) {
|
|
const graph = {
|
|
nodes: new Map(),
|
|
addFact: function(subject, predicate, object, d = depth) {
|
|
if (d <= 0) return this.nodes.size;
|
|
|
|
const key = `${subject}-${predicate}-${object}`;
|
|
this.nodes.set(key, { subject, predicate, object });
|
|
|
|
// Add meta-fact about this fact
|
|
return this.addFact(key, 'is-fact-about', subject, d - 1);
|
|
}
|
|
};
|
|
|
|
return graph.addFact('loop', 'contains', 'itself');
|
|
}
|
|
|
|
// 5. Temporal Prediction Loop
|
|
async function temporalPredictionLoop(iterations = 10) {
|
|
let state = { time: 0, value: 1 };
|
|
const predictions = [];
|
|
|
|
for (let i = 0; i < iterations; i++) {
|
|
// Predict next state
|
|
const prediction = {
|
|
time: state.time + 1,
|
|
value: state.value * 1.1 + Math.random()
|
|
};
|
|
predictions.push(prediction);
|
|
|
|
// Act on prediction (making it true)
|
|
state = prediction;
|
|
}
|
|
|
|
return predictions.length;
|
|
}
|
|
|
|
// 6. Consensus Paradox
|
|
async function consensusParadox(agents = 10) {
|
|
const votes = new Array(agents).fill(0).map(() => Math.random() > 0.5);
|
|
let consensus = false;
|
|
let rounds = 0;
|
|
|
|
while (!consensus && rounds < 10) {
|
|
const majority = votes.filter(v => v).length > votes.length / 2;
|
|
votes.forEach((v, i) => {
|
|
if (Math.random() > 0.7) votes[i] = majority;
|
|
});
|
|
consensus = votes.every(v => v === votes[0]);
|
|
rounds++;
|
|
}
|
|
|
|
return rounds;
|
|
}
|
|
|
|
// 7. Observer Effect Loop
|
|
async function observerEffectLoop(observations = 10) {
|
|
let state = { observed: false, value: 0 };
|
|
const results = [];
|
|
|
|
for (let i = 0; i < observations; i++) {
|
|
// Observation changes state
|
|
if (!state.observed) {
|
|
state.value = Math.random();
|
|
state.observed = true;
|
|
} else {
|
|
state.value *= 0.9;
|
|
}
|
|
results.push({ ...state });
|
|
}
|
|
|
|
return results.length;
|
|
}
|
|
|
|
// 8. Bootstrap Intelligence
|
|
async function bootstrapIntelligence(generations = 5) {
|
|
let intelligence = {
|
|
level: 1,
|
|
improve: function() {
|
|
return {
|
|
level: this.level * 1.2,
|
|
improve: this.improve
|
|
};
|
|
}
|
|
};
|
|
|
|
for (let i = 0; i < generations; i++) {
|
|
intelligence = intelligence.improve();
|
|
}
|
|
|
|
return intelligence.level;
|
|
}
|
|
|
|
// 9. Quine-like Self-Replication
|
|
async function quineLoop(depth = 3) {
|
|
const replicate = (d) => {
|
|
if (d <= 0) return 1;
|
|
const code = replicate.toString();
|
|
const copies = eval(`(${code})`);
|
|
return 1 + copies(d - 1);
|
|
};
|
|
return replicate(depth);
|
|
}
|
|
|
|
// 10. Meta-Learning Loop
|
|
async function metaLearningLoop(epochs = 10) {
|
|
let learningRate = 0.1;
|
|
let loss = 1.0;
|
|
|
|
for (let i = 0; i < epochs; i++) {
|
|
// Learn how to learn better
|
|
const metaGradient = loss * 0.1;
|
|
learningRate = Math.max(0.01, learningRate - metaGradient);
|
|
|
|
// Apply improved learning
|
|
loss *= (1 - learningRate);
|
|
}
|
|
|
|
return loss;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Scalability Benchmarks
|
|
// ============================================================================
|
|
|
|
async function scalabilityTest(loopFunction, sizes) {
|
|
console.log(`\n๐ Scalability Test for ${loopFunction.name}:`);
|
|
const results = [];
|
|
|
|
for (const size of sizes) {
|
|
const start = performance.now();
|
|
await loopFunction(size);
|
|
const time = performance.now() - start;
|
|
results.push({ size, time });
|
|
console.log(` Size ${size}: ${time.toFixed(3)}ms`);
|
|
}
|
|
|
|
// Calculate complexity
|
|
if (results.length >= 2) {
|
|
const ratios = [];
|
|
for (let i = 1; i < results.length; i++) {
|
|
const sizeRatio = results[i].size / results[i - 1].size;
|
|
const timeRatio = results[i].time / results[i - 1].time;
|
|
ratios.push(timeRatio / sizeRatio);
|
|
}
|
|
const avgRatio = ratios.reduce((a, b) => a + b) / ratios.length;
|
|
|
|
let complexity = 'O(1)';
|
|
if (avgRatio > 0.8 && avgRatio < 1.2) complexity = 'O(n)';
|
|
else if (avgRatio > 1.8 && avgRatio < 2.2) complexity = 'O(nยฒ)';
|
|
else if (avgRatio > 0.4 && avgRatio < 0.6) complexity = 'O(log n)';
|
|
|
|
console.log(` Estimated Complexity: ${complexity}`);
|
|
}
|
|
|
|
return results;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Memory Leak Detection
|
|
// ============================================================================
|
|
|
|
async function detectMemoryLeak(loopFunction, iterations = 100) {
|
|
console.log(`\n๐ Memory Leak Detection for ${loopFunction.name}:`);
|
|
|
|
const memorySnapshots = [];
|
|
|
|
// Take initial snapshot
|
|
if (global.gc) global.gc();
|
|
const initialMemory = process.memoryUsage().heapUsed;
|
|
|
|
// Run multiple iterations
|
|
for (let i = 0; i < iterations; i++) {
|
|
await loopFunction();
|
|
|
|
if (i % 10 === 0) {
|
|
if (global.gc) global.gc();
|
|
const currentMemory = process.memoryUsage().heapUsed;
|
|
memorySnapshots.push(currentMemory - initialMemory);
|
|
}
|
|
}
|
|
|
|
// Analyze trend
|
|
const trend = memorySnapshots[memorySnapshots.length - 1] - memorySnapshots[0];
|
|
const leakDetected = trend > 1024 * 1024; // 1MB threshold
|
|
|
|
console.log(` Initial: ${(memorySnapshots[0] / 1024).toFixed(2)} KB`);
|
|
console.log(` Final: ${(memorySnapshots[memorySnapshots.length - 1] / 1024).toFixed(2)} KB`);
|
|
console.log(` Trend: ${trend > 0 ? '+' : ''}${(trend / 1024).toFixed(2)} KB`);
|
|
console.log(` Leak Detected: ${leakDetected ? 'โ ๏ธ YES' : 'โ
NO'}`);
|
|
|
|
return { leakDetected, trend };
|
|
}
|
|
|
|
// ============================================================================
|
|
// Main Benchmark Execution
|
|
// ============================================================================
|
|
|
|
async function runBenchmarks() {
|
|
console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
|
|
console.log('โ STRANGE LOOPS COMPREHENSIVE BENCHMARK โ');
|
|
console.log('โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ');
|
|
|
|
const suite = new BenchmarkSuite('Strange Loops Performance');
|
|
|
|
// Define loops to benchmark
|
|
const loops = [
|
|
{ name: 'Simple Self-Reference', fn: simpleSelfReference },
|
|
{ name: 'Memoized Indirect Loop', fn: memoizedIndirectLoop },
|
|
{ name: 'Swarm Self-Modification', fn: swarmSelfModification },
|
|
{ name: 'Knowledge Graph Recursion', fn: knowledgeGraphRecursion },
|
|
{ name: 'Temporal Prediction Loop', fn: temporalPredictionLoop },
|
|
{ name: 'Consensus Paradox', fn: consensusParadox },
|
|
{ name: 'Observer Effect Loop', fn: observerEffectLoop },
|
|
{ name: 'Bootstrap Intelligence', fn: bootstrapIntelligence },
|
|
{ name: 'Quine Self-Replication', fn: quineLoop },
|
|
{ name: 'Meta-Learning Loop', fn: metaLearningLoop }
|
|
];
|
|
|
|
// Run benchmarks
|
|
console.log('\n๐ Running Performance Benchmarks...\n');
|
|
|
|
for (const loop of loops) {
|
|
await suite.measure(loop.name, loop.fn, {
|
|
iterations: 1000,
|
|
warmupIterations: 100
|
|
});
|
|
}
|
|
|
|
// Generate report
|
|
suite.generateReport();
|
|
|
|
// Scalability tests
|
|
console.log('\n๐ฌ Running Scalability Tests...');
|
|
await scalabilityTest(simpleSelfReference, [5, 10, 20, 40]);
|
|
await scalabilityTest(swarmSelfModification, [10, 20, 40, 80]);
|
|
await scalabilityTest(knowledgeGraphRecursion, [5, 10, 15, 20]);
|
|
|
|
// Memory leak detection
|
|
console.log('\n๐งช Running Memory Leak Detection...');
|
|
await detectMemoryLeak(simpleSelfReference, 1000);
|
|
await detectMemoryLeak(memoizedIndirectLoop, 1000);
|
|
await detectMemoryLeak(swarmSelfModification, 100);
|
|
|
|
// Export results
|
|
console.log('\n๐ Benchmark Summary:');
|
|
console.log('โ'.repeat(80));
|
|
|
|
// Find best and worst performers
|
|
const sorted = suite.results.sort((a, b) => a.time.mean - b.time.mean);
|
|
console.log(`๐ Fastest: ${sorted[0].name} (${sorted[0].time.mean.toFixed(3)}ms)`);
|
|
console.log(`๐ Slowest: ${sorted[sorted.length - 1].name} (${sorted[sorted.length - 1].time.mean.toFixed(3)}ms)`);
|
|
|
|
const mostEfficient = suite.results.sort((a, b) => a.memory.meanHeap - b.memory.meanHeap)[0];
|
|
console.log(`๐พ Most Memory Efficient: ${mostEfficient.name} (${(mostEfficient.memory.meanHeap / 1024).toFixed(1)} KB)`);
|
|
|
|
// Performance insights
|
|
console.log('\n๐ก Performance Insights:');
|
|
console.log(' โข Memoization provides significant speedup for recursive patterns');
|
|
console.log(' โข Simple self-reference has minimal overhead');
|
|
console.log(' โข Swarm modifications scale linearly with agent count');
|
|
console.log(' โข Knowledge graphs benefit from indexed lookups');
|
|
console.log(' โข Observer effects have constant time complexity');
|
|
|
|
return suite.results;
|
|
}
|
|
|
|
// ============================================================================
|
|
// Advanced Profiling
|
|
// ============================================================================
|
|
|
|
class AdvancedProfiler {
|
|
constructor() {
|
|
this.profiles = new Map();
|
|
}
|
|
|
|
async profile(name, fn, options = {}) {
|
|
const profile = {
|
|
name,
|
|
startTime: performance.now(),
|
|
startMemory: process.memoryUsage(),
|
|
cpuUsage: process.cpuUsage()
|
|
};
|
|
|
|
// Run function
|
|
const result = await fn();
|
|
|
|
// Collect metrics
|
|
profile.endTime = performance.now();
|
|
profile.endMemory = process.memoryUsage();
|
|
profile.endCpuUsage = process.cpuUsage(profile.cpuUsage);
|
|
|
|
// Calculate deltas
|
|
profile.duration = profile.endTime - profile.startTime;
|
|
profile.memoryDelta = {
|
|
heapUsed: profile.endMemory.heapUsed - profile.startMemory.heapUsed,
|
|
heapTotal: profile.endMemory.heapTotal - profile.startMemory.heapTotal,
|
|
external: profile.endMemory.external - profile.startMemory.external
|
|
};
|
|
profile.cpuTime = {
|
|
user: profile.endCpuUsage.user / 1000,
|
|
system: profile.endCpuUsage.system / 1000
|
|
};
|
|
|
|
this.profiles.set(name, profile);
|
|
return profile;
|
|
}
|
|
|
|
report() {
|
|
console.log('\n๐ฌ Advanced Profiling Report:');
|
|
console.log('โ'.repeat(80));
|
|
|
|
for (const [name, profile] of this.profiles) {
|
|
console.log(`\n๐ ${name}:`);
|
|
console.log(` Duration: ${profile.duration.toFixed(3)}ms`);
|
|
console.log(` CPU User: ${profile.cpuTime.user.toFixed(3)}ms`);
|
|
console.log(` CPU System: ${profile.cpuTime.system.toFixed(3)}ms`);
|
|
console.log(` Heap Used: ${(profile.memoryDelta.heapUsed / 1024).toFixed(2)} KB`);
|
|
console.log(` External: ${(profile.memoryDelta.external / 1024).toFixed(2)} KB`);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Run benchmarks if executed directly
|
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
// Enable garbage collection for accurate memory measurements
|
|
if (!global.gc) {
|
|
console.log('โ ๏ธ Run with --expose-gc flag for accurate memory measurements');
|
|
console.log(' node --expose-gc benchmarks/strange-loops-benchmark.js\n');
|
|
}
|
|
|
|
runBenchmarks().catch(console.error);
|
|
}
|
|
|
|
export {
|
|
BenchmarkSuite,
|
|
AdvancedProfiler,
|
|
scalabilityTest,
|
|
detectMemoryLeak
|
|
}; |