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)
| Language | Small Files (<1KB) | Medium Files (1-10KB) | Large Files (>10KB) | Very Large (>100KB) |
|---|---|---|---|---|
| JavaScript | 0.3ms | 1.8ms | 12.4ms | 85.2ms |
| TypeScript | 0.5ms | 2.9ms | 19.7ms | 126.8ms |
| Python | 0.4ms | 2.2ms | 15.1ms | 98.5ms |
| Rust | 0.8ms | 3.7ms | 24.9ms | 187.3ms |
| Java | 0.6ms | 2.8ms | 18.3ms | 142.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:
- Enable parser pooling
- Use incremental parsing for edits
- Implement parsing throttling
- 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:
- Implement parser cleanup
- Reduce parser pool size
- Enable garbage collection
- 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:
- Optimize query patterns
- Use query caching
- Implement query batching
- 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
- WebAssembly SIMD: Vectorized parsing operations
- Worker Threads: Parallel parsing for multiple files
- Streaming Parsers: Parse large files incrementally
- Query Compilation: Compile frequent queries to bytecode
- 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