- Create benchmark test suites for critical operations: - Node loading performance - Database query performance - Search operations performance - Validation performance - MCP tool execution performance - Add GitHub Actions workflow for benchmark tracking: - Runs on push to main and PRs - Uses github-action-benchmark for historical tracking - Comments on PRs with performance results - Alerts on >10% performance regressions - Stores results in GitHub Pages - Create benchmark infrastructure: - Custom Vitest benchmark configuration - JSON reporter for CI results - Result formatter for github-action-benchmark - Performance threshold documentation - Add supporting utilities: - SQLiteStorageService for benchmark database setup - MCPEngine wrapper for testing MCP tools - Test factories for generating benchmark data - Enhanced NodeRepository with benchmark methods - Document benchmark system: - Comprehensive benchmark guide in docs/BENCHMARKS.md - Performance thresholds in .github/BENCHMARK_THRESHOLDS.md - README for benchmarks directory - Integration with existing test suite The benchmark system will help monitor performance over time and catch regressions before they reach production. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
204 lines
4.7 KiB
TypeScript
204 lines
4.7 KiB
TypeScript
import { bench, describe } from 'vitest';
|
|
import { MCPEngine } from '../../src/mcp-tools-engine';
|
|
import { NodeRepository } from '../../src/database/node-repository';
|
|
import { SQLiteStorageService } from '../../src/services/sqlite-storage-service';
|
|
import { NodeLoader } from '../../src/loaders/node-loader';
|
|
|
|
describe('MCP Tool Execution Performance', () => {
|
|
let engine: MCPEngine;
|
|
let storage: SQLiteStorageService;
|
|
|
|
beforeAll(async () => {
|
|
storage = new SQLiteStorageService(':memory:');
|
|
const repository = new NodeRepository(storage);
|
|
const loader = new NodeLoader(repository);
|
|
await loader.loadPackage('n8n-nodes-base');
|
|
|
|
engine = new MCPEngine(repository);
|
|
});
|
|
|
|
afterAll(() => {
|
|
storage.close();
|
|
});
|
|
|
|
bench('list_nodes - default limit', async () => {
|
|
await engine.listNodes({});
|
|
}, {
|
|
iterations: 100,
|
|
warmupIterations: 10,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('list_nodes - large limit', async () => {
|
|
await engine.listNodes({ limit: 200 });
|
|
}, {
|
|
iterations: 50,
|
|
warmupIterations: 5,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('list_nodes - filtered by category', async () => {
|
|
await engine.listNodes({ category: 'transform', limit: 100 });
|
|
}, {
|
|
iterations: 100,
|
|
warmupIterations: 10,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('search_nodes - single word', async () => {
|
|
await engine.searchNodes({ query: 'http' });
|
|
}, {
|
|
iterations: 100,
|
|
warmupIterations: 10,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('search_nodes - multiple words', async () => {
|
|
await engine.searchNodes({ query: 'http request webhook', mode: 'OR' });
|
|
}, {
|
|
iterations: 100,
|
|
warmupIterations: 10,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('get_node_info', async () => {
|
|
await engine.getNodeInfo({ nodeType: 'n8n-nodes-base.httpRequest' });
|
|
}, {
|
|
iterations: 500,
|
|
warmupIterations: 50,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('get_node_essentials', async () => {
|
|
await engine.getNodeEssentials({ nodeType: 'n8n-nodes-base.httpRequest' });
|
|
}, {
|
|
iterations: 1000,
|
|
warmupIterations: 100,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('get_node_documentation', async () => {
|
|
await engine.getNodeDocumentation({ nodeType: 'n8n-nodes-base.httpRequest' });
|
|
}, {
|
|
iterations: 500,
|
|
warmupIterations: 50,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('validate_node_operation - simple', async () => {
|
|
await engine.validateNodeOperation({
|
|
nodeType: 'n8n-nodes-base.httpRequest',
|
|
config: {
|
|
url: 'https://api.example.com',
|
|
method: 'GET'
|
|
},
|
|
profile: 'minimal'
|
|
});
|
|
}, {
|
|
iterations: 1000,
|
|
warmupIterations: 100,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('validate_node_operation - complex', async () => {
|
|
await engine.validateNodeOperation({
|
|
nodeType: 'n8n-nodes-base.slack',
|
|
config: {
|
|
resource: 'message',
|
|
operation: 'send',
|
|
channel: 'C1234567890',
|
|
text: 'Hello from benchmark'
|
|
},
|
|
profile: 'strict'
|
|
});
|
|
}, {
|
|
iterations: 500,
|
|
warmupIterations: 50,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('validate_node_minimal', async () => {
|
|
await engine.validateNodeMinimal({
|
|
nodeType: 'n8n-nodes-base.httpRequest',
|
|
config: {}
|
|
});
|
|
}, {
|
|
iterations: 2000,
|
|
warmupIterations: 200,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('search_node_properties', async () => {
|
|
await engine.searchNodeProperties({
|
|
nodeType: 'n8n-nodes-base.httpRequest',
|
|
query: 'authentication'
|
|
});
|
|
}, {
|
|
iterations: 500,
|
|
warmupIterations: 50,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('get_node_for_task', async () => {
|
|
await engine.getNodeForTask({ task: 'post_json_request' });
|
|
}, {
|
|
iterations: 1000,
|
|
warmupIterations: 100,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('list_ai_tools', async () => {
|
|
await engine.listAITools({});
|
|
}, {
|
|
iterations: 100,
|
|
warmupIterations: 10,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('get_database_statistics', async () => {
|
|
await engine.getDatabaseStatistics({});
|
|
}, {
|
|
iterations: 1000,
|
|
warmupIterations: 100,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
|
|
bench('validate_workflow - simple', async () => {
|
|
await engine.validateWorkflow({
|
|
workflow: {
|
|
name: 'Test',
|
|
nodes: [
|
|
{
|
|
id: '1',
|
|
name: 'Manual',
|
|
type: 'n8n-nodes-base.manualTrigger',
|
|
typeVersion: 1,
|
|
position: [250, 300],
|
|
parameters: {}
|
|
}
|
|
],
|
|
connections: {}
|
|
}
|
|
});
|
|
}, {
|
|
iterations: 500,
|
|
warmupIterations: 50,
|
|
warmupTime: 500,
|
|
time: 3000
|
|
});
|
|
}); |