Performance Guide

October 8, 2025 · View on GitHub

Overview

This guide covers performance optimization and monitoring for the AST Copilot Helper project, including parsing performance, memory management, and system resource optimization.

Performance Metrics

Parse Performance

Baseline Performance (Tree-sitter 0.25.x)

LanguageSmall Files (<1KB)Medium Files (1-10KB)Large Files (>10KB)Very Large (>100KB)
JavaScript0.3ms1.8ms12.4ms85.2ms
TypeScript0.5ms2.9ms19.7ms126.8ms
Python0.4ms2.2ms15.1ms98.5ms
Rust0.8ms3.7ms24.9ms187.3ms
Java0.6ms2.8ms18.3ms142.1ms

Performance Improvements (0.25.x vs 0.20.x)

  • Overall: 15-25% faster parsing
  • Memory Usage: 10-15% reduction
  • Error Recovery: 30% faster
  • Query Performance: 20% improvement

Memory Usage Patterns

Memory Consumption by Component

AST Core Engine:     ~8MB base memory
Parser Pool (5):     ~20MB (4MB per parser)
Query Engine:        ~5MB
Symbol Index:        ~10MB per 1000 symbols
Total Baseline:      ~43MB

Memory Scaling

  • Linear Scaling: Memory usage scales linearly with code size
  • Parser Pooling: Reduces memory overhead by 60%
  • Incremental Updates: 70% memory reduction for updates
  • Garbage Collection: Automatic cleanup after 5 minutes idle

Performance Optimization

Parser Configuration

Optimal Settings for Different Use Cases

Interactive Editing (VS Code Extension)

const config = {
  parserPool: {
    maxParsers: 3,
    idleTimeout: 120000, // 2 minutes
    warmupLanguages: ["javascript", "typescript"],
  },
  parsing: {
    incrementalUpdates: true,
    errorRecovery: true,
    includeComments: false,
    cacheResults: true,
  },
};

Batch Processing (CLI Tools)

const config = {
  parserPool: {
    maxParsers: 10,
    idleTimeout: 30000, // 30 seconds
    warmupLanguages: [], // Load on demand
  },
  parsing: {
    incrementalUpdates: false,
    errorRecovery: false,
    includeComments: true,
    cacheResults: false,
  },
};

Server Applications (MCP Server)

const config = {
  parserPool: {
    maxParsers: 5,
    idleTimeout: 300000, // 5 minutes
    warmupLanguages: ["javascript", "typescript", "python"],
  },
  parsing: {
    incrementalUpdates: true,
    errorRecovery: true,
    includeComments: true,
    cacheResults: true,
  },
  memoryLimits: {
    maxHeapSize: 512 * 1024 * 1024, // 512MB
    maxParserMemory: 100 * 1024 * 1024, // 100MB
  },
};

Query Optimization

Efficient Query Patterns

Avoid Overly Broad Queries

// ❌ Inefficient - captures everything
const badQuery = "(_) @node";

// ✅ Efficient - specific targets
const goodQuery = "(function_declaration) @func (class_declaration) @class";

Use Anchored Searches

// ❌ Searches entire tree
const query = '(identifier) @id (#eq? @id "targetName")';

// ✅ Anchored to specific context
const query =
  '(function_declaration name: (identifier) @name (#eq? @name "targetName"))';

Batch Multiple Queries

// ❌ Multiple separate queries
const functions = queryAST(ast, "(function_declaration) @func");
const classes = queryAST(ast, "(class_declaration) @class");

// ✅ Single combined query
const symbols = queryAST(
  ast,
  `
  (function_declaration) @function
  (class_declaration) @class
  (variable_declarator) @variable
`,
);

Memory Management

Parser Pool Configuration

class OptimizedParserPool {
  constructor() {
    this.maxParsers = this.calculateOptimalPoolSize();
    this.gcThreshold = 100 * 1024 * 1024; // 100MB
    this.idleCleanup = 300000; // 5 minutes
  }

  calculateOptimalPoolSize(): number {
    const totalMemory = process.memoryUsage().heapTotal;
    const availableMemory = totalMemory * 0.3; // Use 30% for parsers
    return Math.min(Math.floor(availableMemory / (20 * 1024 * 1024)), 10);
  }
}

Memory Monitoring

function monitorMemoryUsage() {
  const usage = process.memoryUsage();

  if (usage.heapUsed > this.gcThreshold) {
    // Force garbage collection if available
    if (global.gc) {
      global.gc();
    }

    // Clean up idle parsers
    this.cleanupIdleParsers();
  }

  return {
    heapUsed: usage.heapUsed,
    heapTotal: usage.heapTotal,
    external: usage.external,
    rss: usage.rss,
  };
}

Platform-Specific Optimizations

Windows Optimizations

const windowsConfig = {
  // Use shorter paths to avoid Windows path limits
  maxPathLength: 260,

  // Optimize for NTFS
  fileSystemCache: true,

  // Windows-specific memory management
  memoryStrategy: "conservative",

  // Use Windows threading
  useWindowsThreading: true,
};

macOS Optimizations

const macosConfig = {
  // Leverage macOS file system features
  useSpotlightCache: true,

  // Apple Silicon optimizations
  architecture: process.arch === "arm64" ? "arm64" : "x64",

  // Core Foundation integration
  useCoreFoundation: true,
};

Linux Optimizations

const linuxConfig = {
  // Use inotify for file watching
  useInotify: true,

  // Optimize for different distributions
  distribution: detectLinuxDistribution(),

  // Memory mapping optimizations
  useMemoryMapping: true,

  // NUMA awareness
  numaAware: true,
};

Performance Monitoring

Built-in Performance Metrics

import { PerformanceMonitor } from "@ast-copilot-helper/core";

const monitor = new PerformanceMonitor({
  enableProfiling: true,
  sampleRate: 0.1, // 10% sampling
  metricsInterval: 30000, // 30 seconds
});

// Monitor parsing performance
monitor.trackParsing(async () => {
  const ast = await parseCode(sourceCode, "javascript");
  return ast;
});

// Get performance report
const report = monitor.generateReport();
console.log(report);

Custom Performance Tracking

class PerformanceTracker {
  private metrics = new Map();

  startTimer(operation: string): string {
    const id = `${operation}-${Date.now()}`;
    this.metrics.set(id, {
      operation,
      startTime: performance.now(),
      startMemory: process.memoryUsage(),
    });
    return id;
  }

  endTimer(id: string): PerformanceResult {
    const metric = this.metrics.get(id);
    if (!metric) throw new Error(`No metric found for ${id}`);

    const endTime = performance.now();
    const endMemory = process.memoryUsage();

    return {
      operation: metric.operation,
      duration: endTime - metric.startTime,
      memoryDelta: endMemory.heapUsed - metric.startMemory.heapUsed,
      peakMemory: endMemory.heapUsed,
    };
  }
}

Performance Testing

Benchmark Suite

import { BenchmarkSuite } from "@ast-copilot-helper/testing";

const suite = new BenchmarkSuite({
  iterations: 100,
  warmupIterations: 10,
  timeout: 30000,
});

// Add benchmarks
suite.add("parse-javascript", async () => {
  return await parseCode(jsCode, "javascript");
});

suite.add("parse-typescript", async () => {
  return await parseCode(tsCode, "typescript");
});

// Run benchmarks
const results = await suite.run();
console.log(results);

Performance Regression Testing

describe("Performance Regression Tests", () => {
  test("JavaScript parsing should not regress", async () => {
    const startTime = performance.now();
    const ast = await parseCode(sampleCode, "javascript");
    const duration = performance.now() - startTime;

    // Assert performance baseline
    expect(duration).toBeLessThan(50); // 50ms for sample code
    expect(ast.hasErrors()).toBe(false);
  });
});

Performance Troubleshooting

Common Performance Issues

Issue: Slow Parsing Performance

Symptoms:

  • Parse times > 100ms for small files
  • High CPU usage during parsing
  • UI freezing in interactive applications

Solutions:

  1. Enable parser pooling
  2. Use incremental parsing for edits
  3. Implement parsing throttling
  4. Check for memory leaks

Issue: High Memory Usage

Symptoms:

  • Memory usage > 500MB for typical workloads
  • Memory not being freed after parsing
  • Out of memory errors

Solutions:

  1. Implement parser cleanup
  2. Reduce parser pool size
  3. Enable garbage collection
  4. Use streaming for large files

Issue: Query Performance Problems

Symptoms:

  • Query times > 10ms for simple queries
  • Exponential time complexity
  • High memory usage during queries

Solutions:

  1. Optimize query patterns
  2. Use query caching
  3. Implement query batching
  4. Add query timeouts

Profiling Tools

Node.js Profiling

# CPU profiling
node --prof app.js

# Memory profiling
node --inspect app.js

# Heap snapshots
node --inspect --inspect-brk app.js

Browser Profiling

// Performance API
performance.mark("parse-start");
const ast = await parseCode(code, "javascript");
performance.mark("parse-end");
performance.measure("parse-duration", "parse-start", "parse-end");

// Memory profiling
const memoryBefore = performance.memory?.usedJSHeapSize || 0;
const ast = await parseCode(code, "javascript");
const memoryAfter = performance.memory?.usedJSHeapSize || 0;
const memoryUsed = memoryAfter - memoryBefore;

Performance Configuration Examples

High-Performance Server Setup

const serverConfig = {
  parsers: {
    poolSize: 20,
    warmupLanguages: ["javascript", "typescript", "python"],
    idleTimeout: 600000, // 10 minutes
    maxMemoryPerParser: 50 * 1024 * 1024, // 50MB
  },
  caching: {
    enabled: true,
    maxCacheSize: 1000,
    ttl: 3600000, // 1 hour
  },
  monitoring: {
    metricsEnabled: true,
    profileSampling: 0.01, // 1% sampling
    alertThresholds: {
      parseTime: 1000, // 1 second
      memoryUsage: 1024 * 1024 * 1024, // 1GB
    },
  },
};

Resource-Constrained Environment

const constrainedConfig = {
  parsers: {
    poolSize: 2,
    warmupLanguages: [], // Load on demand
    idleTimeout: 60000, // 1 minute
    maxMemoryPerParser: 20 * 1024 * 1024, // 20MB
  },
  caching: {
    enabled: false, // Disable to save memory
  },
  parsing: {
    incrementalUpdates: false,
    errorRecovery: false,
    includeComments: false,
  },
};

Future Performance Improvements

Planned Optimizations

  1. WebAssembly SIMD: Vectorized parsing operations
  2. Worker Threads: Parallel parsing for multiple files
  3. Streaming Parsers: Parse large files incrementally
  4. Query Compilation: Compile frequent queries to bytecode
  5. Memory Mapping: Direct file memory access

Performance Roadmap

  • Q1 2025: WebAssembly SIMD support
  • Q2 2025: Worker thread integration
  • Q3 2025: Streaming parser implementation
  • Q4 2025: Advanced query optimization

For implementation details, see the Tree-sitter Integration Guide