about summary refs log tree commit diff stats
path: root/js/baba-yaga/src/benchmarks/benchmark-suite.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/baba-yaga/src/benchmarks/benchmark-suite.js')
-rw-r--r--js/baba-yaga/src/benchmarks/benchmark-suite.js359
1 files changed, 359 insertions, 0 deletions
diff --git a/js/baba-yaga/src/benchmarks/benchmark-suite.js b/js/baba-yaga/src/benchmarks/benchmark-suite.js
new file mode 100644
index 0000000..a01bfbd
--- /dev/null
+++ b/js/baba-yaga/src/benchmarks/benchmark-suite.js
@@ -0,0 +1,359 @@
+// benchmark-suite.js - Comprehensive performance benchmarking suite
+
+import { benchmarkLexers } from './lexer-optimized.js';
+import { benchmarkScopes } from './scope-stack.js';
+import { benchmarkBuiltins } from './builtins-optimized.js';
+import { benchmarkASTPool } from './ast-pool.js';
+import { BabaYagaEngine } from './engine.js';
+import { BabaYagaConfig } from './config.js';
+
+/**
+ * Comprehensive benchmark suite for measuring performance improvements
+ */
+export class BenchmarkSuite {
+  constructor() {
+    this.results = {};
+    this.testPrograms = this.createTestPrograms();
+  }
+
+  /**
+   * Create test programs of varying complexity
+   */
+  createTestPrograms() {
+    return {
+      simple: `
+        x : 42;
+        y : x + 8;
+        io.out y;
+      `,
+      
+      arithmetic: `
+        add : x y -> x + y;
+        multiply : x y -> x * y;
+        result : multiply (add 10 20) (add 5 15);
+        io.out result;
+      `,
+      
+      listProcessing: `
+        numbers : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+        doubled : map (x -> x * 2) numbers;
+        evens : filter (x -> x % 2 = 0) doubled;
+        sum : reduce (acc x -> acc + x) 0 evens;
+        io.out sum;
+      `,
+      
+      recursion: `
+        factorial : n ->
+          when n is
+            0 then 1
+            1 then 1
+            _ then n * (factorial (n - 1));
+        result : factorial 10;
+        io.out result;
+      `,
+      
+      patternMatching: `
+        processValue : x ->
+          when x is
+            0 then "zero"
+            1 then "one"
+            Int then "integer"
+            String then "string"
+            _ then "other";
+        
+        values : [0, 1, 42, "hello", true];
+        results : map processValue values;
+        io.out results;
+      `,
+      
+      complexNested: `
+        fibonacci : n ->
+          when n is
+            0 then 0
+            1 then 1
+            _ then (fibonacci (n - 1)) + (fibonacci (n - 2));
+        
+        range : n -> with rec (
+          helper : i acc ->
+            when i is
+              0 then acc
+              _ then helper (i - 1) (prepend i acc);
+        ) -> helper n [];
+        
+        fibNumbers : map fibonacci (range 15);
+        evenFibs : filter (x -> x % 2 = 0) fibNumbers;
+        result : reduce (acc x -> acc + x) 0 evenFibs;
+        io.out result;
+      `
+    };
+  }
+
+  /**
+   * Run all benchmarks
+   */
+  async runAll() {
+    console.log('๐Ÿš€ Starting Baba Yaga Performance Benchmark Suite\n');
+    
+    await this.benchmarkComponents();
+    await this.benchmarkPrograms();
+    await this.generateReport();
+    
+    return this.results;
+  }
+
+  /**
+   * Benchmark individual components
+   */
+  async benchmarkComponents() {
+    console.log('๐Ÿ“Š Benchmarking Individual Components\n');
+    
+    // Lexer benchmarks
+    console.log('๐Ÿ”ค Lexer Performance:');
+    this.results.lexer = await benchmarkLexers(this.testPrograms.complexNested, 1000);
+    console.log('');
+    
+    // Scope stack benchmarks
+    console.log('๐Ÿ“š Scope Stack Performance:');
+    this.results.scopes = await benchmarkScopes(50000);
+    console.log('');
+    
+    // Built-in functions benchmarks
+    console.log('โšก Built-in Functions Performance:');
+    this.results.builtins = await benchmarkBuiltins(5000);
+    console.log('');
+    
+    // AST Pool benchmarks
+    console.log('๐ŸŠ AST Object Pool Performance:');
+    this.results.astPool = await benchmarkASTPool(50000);
+    console.log('');
+  }
+
+  /**
+   * Benchmark complete programs
+   */
+  async benchmarkPrograms() {
+    console.log('๐Ÿ“‹ Benchmarking Complete Programs\n');
+    
+    this.results.programs = {};
+    
+    for (const [name, code] of Object.entries(this.testPrograms)) {
+      console.log(`๐Ÿงช Testing ${name}:`);
+      
+      const result = await this.benchmarkProgram(code, name);
+      this.results.programs[name] = result;
+      
+      console.log(`  Original: ${result.originalTime.toFixed(2)}ms`);
+      console.log(`  Optimized: ${result.optimizedTime.toFixed(2)}ms`);
+      console.log(`  Speedup: ${result.speedup.toFixed(2)}x`);
+      console.log('');
+    }
+  }
+
+  /**
+   * Benchmark a single program with both engines
+   */
+  async benchmarkProgram(code, name, iterations = 1000) {
+    // Benchmark original engine
+    const originalConfig = new BabaYagaConfig({
+      enableOptimizations: false,
+      enableDebugMode: false
+    });
+    const originalEngine = new BabaYagaEngine(originalConfig);
+    
+    // Warm up
+    for (let i = 0; i < 10; i++) {
+      await originalEngine.execute(code);
+    }
+    
+    const originalStart = performance.now();
+    for (let i = 0; i < iterations; i++) {
+      await originalEngine.execute(code);
+    }
+    const originalTime = performance.now() - originalStart;
+    
+    // Benchmark optimized engine
+    const optimizedConfig = new BabaYagaConfig({
+      enableOptimizations: true,
+      enableDebugMode: false
+    });
+    const optimizedEngine = new BabaYagaEngine(optimizedConfig);
+    
+    // Warm up
+    for (let i = 0; i < 10; i++) {
+      await optimizedEngine.execute(code);
+    }
+    
+    const optimizedStart = performance.now();
+    for (let i = 0; i < iterations; i++) {
+      await optimizedEngine.execute(code);
+    }
+    const optimizedTime = performance.now() - optimizedStart;
+    
+    return {
+      name,
+      iterations,
+      originalTime,
+      optimizedTime,
+      speedup: originalTime / optimizedTime,
+      originalStats: originalEngine.getStats(),
+      optimizedStats: optimizedEngine.getStats()
+    };
+  }
+
+  /**
+   * Generate comprehensive performance report
+   */
+  async generateReport() {
+    console.log('๐Ÿ“ˆ Performance Summary Report\n');
+    console.log('=' .repeat(60));
+    
+    // Component improvements
+    console.log('\n๐Ÿ”ง Component-Level Improvements:');
+    console.log(`  Lexer:          ${this.results.lexer.speedup.toFixed(2)}x faster`);
+    console.log(`  Scope Stack:    ${this.results.scopes.speedup.toFixed(2)}x faster`);
+    console.log(`  Built-ins:      ${this.results.builtins.speedup.toFixed(2)}x faster`);
+    console.log(`  AST Pool:       ${this.results.astPool.speedup.toFixed(2)}x faster`);
+    
+    // Program-level improvements
+    console.log('\n๐Ÿš€ Program-Level Improvements:');
+    let totalSpeedup = 0;
+    let programCount = 0;
+    
+    for (const [name, result] of Object.entries(this.results.programs)) {
+      console.log(`  ${name.padEnd(15)}: ${result.speedup.toFixed(2)}x faster`);
+      totalSpeedup += result.speedup;
+      programCount++;
+    }
+    
+    const averageSpeedup = totalSpeedup / programCount;
+    console.log(`  Average:        ${averageSpeedup.toFixed(2)}x faster`);
+    
+    // Memory and efficiency improvements
+    console.log('\n๐Ÿ’พ Memory & Efficiency:');
+    const astStats = this.results.astPool.stats;
+    console.log(`  AST Pool Hit Rate:    ${(astStats.hitRate * 100).toFixed(1)}%`);
+    console.log(`  Object Reuse Rate:    ${(astStats.reuseRate * 100).toFixed(1)}%`);
+    console.log(`  Total Objects Pooled: ${astStats.totalPooledObjects}`);
+    
+    const scopeStats = this.results.scopes.stats;
+    console.log(`  Scope Hit Rate:       ${(scopeStats.hitRate * 100).toFixed(1)}%`);
+    console.log(`  Variable Slots:       ${scopeStats.totalSlots}`);
+    
+    // Recommendations
+    console.log('\n๐Ÿ’ก Optimization Impact Summary:');
+    console.log(`  ๐ŸŽฏ Best improvement: ${this.getBestImprovement()}`);
+    console.log(`  ๐Ÿ“Š Overall speedup:  ${averageSpeedup.toFixed(2)}x`);
+    console.log(`  ๐Ÿ”‹ Memory efficiency: ${this.getMemoryEfficiency()}`);
+    
+    console.log('\n' + '=' .repeat(60));
+  }
+
+  /**
+   * Identify the best performing optimization
+   */
+  getBestImprovement() {
+    const improvements = {
+      'Lexer': this.results.lexer.speedup,
+      'Scope Stack': this.results.scopes.speedup,
+      'Built-ins': this.results.builtins.speedup,
+      'AST Pool': this.results.astPool.speedup
+    };
+    
+    let best = { name: '', speedup: 0 };
+    for (const [name, speedup] of Object.entries(improvements)) {
+      if (speedup > best.speedup) {
+        best = { name, speedup };
+      }
+    }
+    
+    return `${best.name} (${best.speedup.toFixed(2)}x)`;
+  }
+
+  /**
+   * Calculate overall memory efficiency improvement
+   */
+  getMemoryEfficiency() {
+    const astHitRate = this.results.astPool.stats.hitRate;
+    const scopeHitRate = this.results.scopes.stats.hitRate;
+    const avgHitRate = (astHitRate + scopeHitRate) / 2;
+    
+    if (avgHitRate > 0.8) return 'Excellent';
+    if (avgHitRate > 0.6) return 'Good';
+    if (avgHitRate > 0.4) return 'Fair';
+    return 'Needs improvement';
+  }
+
+  /**
+   * Save results to file
+   */
+  async saveResults(filename = 'benchmark-results.json') {
+    const fs = await import('fs');
+    const resultsWithMetadata = {
+      timestamp: new Date().toISOString(),
+      nodeVersion: process.version,
+      platform: process.platform,
+      arch: process.arch,
+      ...this.results
+    };
+    
+    fs.writeFileSync(filename, JSON.stringify(resultsWithMetadata, null, 2));
+    console.log(`\n๐Ÿ’พ Results saved to ${filename}`);
+  }
+}
+
+/**
+ * Quick benchmark function for CLI usage
+ */
+export async function quickBenchmark() {
+  const suite = new BenchmarkSuite();
+  return await suite.runAll();
+}
+
+/**
+ * Memory usage benchmark
+ */
+export async function benchmarkMemoryUsage() {
+  console.log('๐Ÿง  Memory Usage Benchmark\n');
+  
+  const testCode = `
+    range : n -> with rec (
+      helper : i acc ->
+        when i is
+          0 then acc
+          _ then helper (i - 1) (prepend i acc);
+    ) -> helper n [];
+    
+    numbers : range 1000;
+    doubled : map (x -> x * 2) numbers;
+    filtered : filter (x -> x > 100) doubled;
+    result : reduce (acc x -> acc + x) 0 filtered;
+  `;
+  
+  // Measure memory before
+  const memBefore = process.memoryUsage();
+  
+  // Run multiple iterations
+  const engine = new BabaYagaEngine();
+  for (let i = 0; i < 100; i++) {
+    await engine.execute(testCode);
+  }
+  
+  // Force garbage collection if available
+  if (global.gc) {
+    global.gc();
+  }
+  
+  // Measure memory after
+  const memAfter = process.memoryUsage();
+  
+  console.log('Memory Usage:');
+  console.log(`  Heap Used:     ${((memAfter.heapUsed - memBefore.heapUsed) / 1024 / 1024).toFixed(2)} MB`);
+  console.log(`  Heap Total:    ${((memAfter.heapTotal - memBefore.heapTotal) / 1024 / 1024).toFixed(2)} MB`);
+  console.log(`  External:      ${((memAfter.external - memBefore.external) / 1024 / 1024).toFixed(2)} MB`);
+  
+  return {
+    heapUsedDiff: memAfter.heapUsed - memBefore.heapUsed,
+    heapTotalDiff: memAfter.heapTotal - memBefore.heapTotal,
+    externalDiff: memAfter.external - memBefore.external
+  };
+}