import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { performance } from "perf_hooks";
import { logger } from "../monitoring/logger.js";
import { StreamingJSONLParser } from "./streaming-jsonl-parser.js";
import { ContextCache } from "./context-cache.js";
import { LazyContextLoader } from "./lazy-context-loader.js";
import { readFileSync } from "fs";
import { join } from "path";
class PerformanceBenchmark {
  results = [];
  /**
   * Benchmark JSONL parsing performance
   */
  async benchmarkJSONLParsing(filePath, iterations = 3) {
    const parser = new StreamingJSONLParser();
    const baselineStart = performance.now();
    const baselineMemStart = process.memoryUsage().heapUsed;
    let baselineCount = 0;
    for (let i = 0; i < iterations; i++) {
      const content = readFileSync(filePath, "utf8");
      const lines = content.split("\n").filter((l) => l.trim());
      for (const line of lines) {
        try {
          JSON.parse(line);
          baselineCount++;
        } catch {
        }
      }
    }
    const baselineDuration = performance.now() - baselineStart;
    const baselineMemUsed = process.memoryUsage().heapUsed - baselineMemStart;
    const optimizedStart = performance.now();
    const optimizedMemStart = process.memoryUsage().heapUsed;
    let optimizedCount = 0;
    for (let i = 0; i < iterations; i++) {
      for await (const batch of parser.parseStream(filePath)) {
        optimizedCount += batch.length;
      }
    }
    const optimizedDuration = performance.now() - optimizedStart;
    const optimizedMemUsed = process.memoryUsage().heapUsed - optimizedMemStart;
    const improvement = (baselineDuration - optimizedDuration) / baselineDuration * 100;
    const memImprovement = (baselineMemUsed - optimizedMemUsed) / baselineMemUsed * 100;
    const result = {
      name: "JSONL Parsing",
      duration: optimizedDuration / iterations,
      memoryUsed: optimizedMemUsed,
      itemsProcessed: optimizedCount / iterations,
      throughput: optimizedCount / iterations / (optimizedDuration / 1e3 / iterations),
      improvement
    };
    logger.info("JSONL Parsing Benchmark", {
      baseline: {
        duration: baselineDuration / iterations,
        memory: baselineMemUsed,
        throughput: baselineCount / iterations / (baselineDuration / 1e3 / iterations)
      },
      optimized: result,
      improvements: {
        speed: `${improvement.toFixed(1)}%`,
        memory: `${memImprovement.toFixed(1)}%`
      }
    });
    this.results.push(result);
    return result;
  }
  /**
   * Benchmark context caching performance
   */
  async benchmarkContextCache(itemCount = 1e3, accessPatterns = 1e4) {
    const cache = new ContextCache({
      maxSize: 50 * 1024 * 1024,
      maxItems: itemCount
    });
    const testData = Array.from({ length: itemCount }, (_, i) => ({
      key: `item-${i}`,
      value: {
        id: i,
        data: "x".repeat(Math.floor(Math.random() * 1e3)),
        timestamp: Date.now()
      }
    }));
    const populateStart = performance.now();
    for (const item of testData) {
      cache.set(item.key, item.value);
    }
    const populateDuration = performance.now() - populateStart;
    const accessStart = performance.now();
    let hits = 0;
    let misses = 0;
    for (let i = 0; i < accessPatterns; i++) {
      const index = Math.floor(Math.random() * itemCount * 1.2);
      const key = `item-${index}`;
      const result2 = cache.get(key);
      if (result2) hits++;
      else misses++;
    }
    const accessDuration = performance.now() - accessStart;
    const stats = cache.getStats();
    const result = {
      name: "Context Cache",
      duration: accessDuration,
      memoryUsed: cache.getSize().bytes,
      itemsProcessed: accessPatterns,
      throughput: accessPatterns / (accessDuration / 1e3),
      improvement: stats.hitRate * 100
    };
    logger.info("Context Cache Benchmark", {
      populate: {
        duration: populateDuration,
        items: itemCount
      },
      access: {
        duration: accessDuration,
        patterns: accessPatterns,
        hitRate: `${(stats.hitRate * 100).toFixed(1)}%`
      },
      performance: {
        throughput: `${result.throughput.toFixed(0)} ops/sec`,
        avgAccessTime: `${stats.avgAccessTime.toFixed(2)}ms`
      }
    });
    this.results.push(result);
    return result;
  }
  /**
   * Benchmark lazy loading performance
   */
  async benchmarkLazyLoading(db, projectId, frameCount = 100) {
    const loader = new LazyContextLoader(db, projectId);
    let frames = [];
    try {
      frames = db.prepare("SELECT id FROM frames ORDER BY updated_at DESC LIMIT ?").all(frameCount);
    } catch (error) {
      logger.warn("Frames table not found, using mock data for benchmark");
      frames = Array.from({ length: Math.min(frameCount, 10) }, (_, i) => ({
        id: `frame-${i}`
      }));
    }
    const frameIds = frames.map((f) => f.id);
    const eagerStart = performance.now();
    const eagerMemStart = process.memoryUsage().heapUsed;
    const eagerData = [];
    for (const id of frameIds) {
      try {
        const frame = db.prepare("SELECT * FROM frames WHERE id = ?").get(id);
        const anchors = db.prepare("SELECT * FROM anchors WHERE frame_id = ?").all(id);
        const events = db.prepare("SELECT * FROM events WHERE frame_id = ? LIMIT 10").all(id);
        eagerData.push({ frame, anchors, events });
      } catch {
        eagerData.push({
          frame: { id, type: "mock", name: `Mock ${id}` },
          anchors: [],
          events: []
        });
      }
    }
    const eagerDuration = performance.now() - eagerStart;
    const eagerMemUsed = process.memoryUsage().heapUsed - eagerMemStart;
    const lazyStart = performance.now();
    const lazyMemStart = process.memoryUsage().heapUsed;
    await loader.preloadContext(frameIds, { parallel: true, depth: 2 });
    let accessedCount = 0;
    for (const id of frameIds.slice(0, frameCount / 2)) {
      const frame = await loader.lazyFrame(id).get();
      if (frame) accessedCount++;
    }
    const lazyDuration = performance.now() - lazyStart;
    const lazyMemUsed = process.memoryUsage().heapUsed - lazyMemStart;
    const improvement = (eagerDuration - lazyDuration) / eagerDuration * 100;
    const memImprovement = (eagerMemUsed - lazyMemUsed) / eagerMemUsed * 100;
    const result = {
      name: "Lazy Loading",
      duration: lazyDuration,
      memoryUsed: lazyMemUsed,
      itemsProcessed: frameCount,
      throughput: frameCount / (lazyDuration / 1e3),
      improvement
    };
    logger.info("Lazy Loading Benchmark", {
      eager: {
        duration: eagerDuration,
        memory: eagerMemUsed
      },
      lazy: {
        duration: lazyDuration,
        memory: lazyMemUsed,
        accessed: accessedCount
      },
      improvements: {
        speed: `${improvement.toFixed(1)}%`,
        memory: `${memImprovement.toFixed(1)}%`
      }
    });
    this.results.push(result);
    return result;
  }
  /**
   * Run full benchmark suite
   */
  async runFullSuite(projectRoot, db, projectId) {
    const suiteStart = performance.now();
    logger.info("Starting Performance Benchmark Suite");
    const tasksFile = join(projectRoot, ".stackmemory", "tasks.jsonl");
    const jsonlResult = await this.benchmarkJSONLParsing(tasksFile);
    const cacheResult = await this.benchmarkContextCache();
    const lazyResult = await this.benchmarkLazyLoading(db, projectId);
    const totalDuration = performance.now() - suiteStart;
    const averageImprovement = this.results.filter((r) => r.improvement !== void 0).reduce((sum, r) => sum + (r.improvement || 0), 0) / this.results.filter((r) => r.improvement !== void 0).length;
    const suite = {
      name: "Performance Optimization Suite",
      results: this.results,
      totalDuration,
      averageImprovement
    };
    this.generateReport(suite);
    return suite;
  }
  /**
   * Generate performance report
   */
  generateReport(suite) {
    console.log("\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
    console.log("\u2551     Performance Benchmark Results         \u2551");
    console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n");
    for (const result of suite.results) {
      console.log(`\u{1F4CA} ${result.name}`);
      console.log(`   Duration: ${result.duration.toFixed(2)}ms`);
      console.log(
        `   Memory: ${(result.memoryUsed / 1024 / 1024).toFixed(2)}MB`
      );
      console.log(`   Throughput: ${result.throughput.toFixed(0)} items/sec`);
      if (result.improvement !== void 0) {
        const icon = result.improvement > 0 ? "\u{1F680}" : "\u26A0\uFE0F";
        console.log(
          `   ${icon} Improvement: ${result.improvement.toFixed(1)}%`
        );
      }
      console.log("");
    }
    console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
    console.log(`\u23F1\uFE0F  Total Duration: ${suite.totalDuration.toFixed(2)}ms`);
    console.log(
      `\u{1F4C8} Average Improvement: ${suite.averageImprovement.toFixed(1)}%`
    );
    console.log("");
    logger.info("Performance Benchmark Complete", {
      suite: suite.name,
      duration: suite.totalDuration,
      avgImprovement: suite.averageImprovement,
      results: suite.results.map((r) => ({
        name: r.name,
        improvement: r.improvement,
        throughput: r.throughput
      }))
    });
  }
  /**
   * Get benchmark results
   */
  getResults() {
    return this.results;
  }
  /**
   * Clear results
   */
  clearResults() {
    this.results = [];
  }
}
export {
  PerformanceBenchmark
};
//# sourceMappingURL=performance-benchmark.js.map
