@ruvector/postgres-cli
Version:
Advanced AI vector database CLI for PostgreSQL - pgvector drop-in replacement with 53+ SQL functions, 39 attention mechanisms, GNN layers, hyperbolic embeddings, and self-learning capabilities
198 lines (187 loc) • 7.87 kB
JavaScript
/**
* Benchmark Commands
* CLI commands for performance benchmarking
*/
import chalk from 'chalk';
import ora from 'ora';
import Table from 'cli-table3';
export class BenchmarkCommands {
static async run(client, options) {
const spinner = ora('Running benchmarks...').start();
try {
await client.connect();
const size = parseInt(options.size);
const dim = parseInt(options.dim);
const results = [];
// Vector benchmarks
if (options.type === 'vector' || options.type === 'all') {
spinner.text = 'Running vector benchmarks...';
const vectorResult = await client.runBenchmark('vector', size, dim);
results.push({
name: 'Vector Search',
operations: size,
totalTime: vectorResult.total_time,
avgTime: vectorResult.avg_time,
opsPerSec: vectorResult.ops_per_sec,
p50: vectorResult.p50,
p95: vectorResult.p95,
p99: vectorResult.p99,
});
}
// Attention benchmarks
if (options.type === 'attention' || options.type === 'all') {
spinner.text = 'Running attention benchmarks...';
const attentionResult = await client.runBenchmark('attention', size, dim);
results.push({
name: 'Attention',
operations: size,
totalTime: attentionResult.total_time,
avgTime: attentionResult.avg_time,
opsPerSec: attentionResult.ops_per_sec,
p50: attentionResult.p50,
p95: attentionResult.p95,
p99: attentionResult.p99,
});
}
// GNN benchmarks
if (options.type === 'gnn' || options.type === 'all') {
spinner.text = 'Running GNN benchmarks...';
const gnnResult = await client.runBenchmark('gnn', size, dim);
results.push({
name: 'GNN Forward',
operations: size,
totalTime: gnnResult.total_time,
avgTime: gnnResult.avg_time,
opsPerSec: gnnResult.ops_per_sec,
p50: gnnResult.p50,
p95: gnnResult.p95,
p99: gnnResult.p99,
});
}
spinner.succeed(chalk.green('Benchmarks completed'));
// Display results
console.log(chalk.bold.blue('\nBenchmark Results:'));
console.log(chalk.gray('─'.repeat(70)));
console.log(` ${chalk.gray('Dataset Size:')} ${size.toLocaleString()}`);
console.log(` ${chalk.gray('Dimensions:')} ${dim}`);
const table = new Table({
head: [
chalk.cyan('Benchmark'),
chalk.cyan('Ops/sec'),
chalk.cyan('Avg (ms)'),
chalk.cyan('P50 (ms)'),
chalk.cyan('P95 (ms)'),
chalk.cyan('P99 (ms)')
],
colWidths: [18, 12, 12, 12, 12, 12]
});
for (const result of results) {
table.push([
result.name,
result.opsPerSec.toFixed(0),
result.avgTime.toFixed(3),
result.p50.toFixed(3),
result.p95.toFixed(3),
result.p99.toFixed(3)
]);
}
console.log(table.toString());
// Summary
const totalOps = results.reduce((sum, r) => sum + r.opsPerSec, 0);
console.log(`\n ${chalk.green('Total Throughput:')} ${totalOps.toFixed(0)} ops/sec`);
}
catch (err) {
spinner.fail(chalk.red('Benchmark failed'));
console.error(chalk.red(err.message));
}
finally {
await client.disconnect();
}
}
static async report(client, options) {
const spinner = ora('Generating benchmark report...').start();
try {
await client.connect();
// Get historical benchmark results
const results = await client.query('SELECT * FROM benchmark_results ORDER BY created_at DESC LIMIT 10');
spinner.stop();
if (results.length === 0) {
console.log(chalk.yellow('No benchmark results found'));
console.log(chalk.gray('Run benchmarks first: ruvector-pg bench run'));
return;
}
if (options.format === 'json') {
console.log(JSON.stringify(results, null, 2));
return;
}
if (options.format === 'markdown') {
console.log('# Benchmark Report\n');
console.log('| Type | Date | Ops/sec | Avg Time |');
console.log('|------|------|---------|----------|');
for (const result of results) {
const metrics = result.metrics;
console.log(`| ${result.benchmark_type} | ${result.created_at} | ` +
`${metrics.ops_per_sec?.toFixed(0) || 'N/A'} | ` +
`${metrics.avg_time?.toFixed(3) || 'N/A'}ms |`);
}
return;
}
// Default: table format
console.log(chalk.bold.blue('\nBenchmark History:'));
console.log(chalk.gray('─'.repeat(70)));
const table = new Table({
head: [
chalk.cyan('ID'),
chalk.cyan('Type'),
chalk.cyan('Date'),
chalk.cyan('Ops/sec'),
chalk.cyan('Avg (ms)')
],
colWidths: [8, 15, 25, 12, 12]
});
for (const result of results) {
const metrics = result.metrics;
table.push([
String(result.id),
result.benchmark_type,
result.created_at,
metrics.ops_per_sec?.toFixed(0) || 'N/A',
metrics.avg_time?.toFixed(3) || 'N/A'
]);
}
console.log(table.toString());
}
catch (err) {
spinner.fail(chalk.red('Failed to generate report'));
console.error(chalk.red(err.message));
}
finally {
await client.disconnect();
}
}
static showInfo() {
console.log(chalk.bold.blue('\nBenchmark System:'));
console.log(chalk.gray('─'.repeat(50)));
console.log(`
${chalk.yellow('Available Benchmarks:')}
${chalk.green('vector')} - Vector similarity search performance
HNSW index operations, cosine/L2/IP distances
${chalk.green('attention')} - Attention mechanism throughput
Scaled dot-product, multi-head, flash attention
${chalk.green('gnn')} - Graph Neural Network performance
GCN, GraphSAGE, GAT, GIN forward passes
${chalk.green('all')} - Run all benchmarks sequentially
${chalk.yellow('Options:')}
${chalk.gray('-s, --size')} Dataset size (default: 10000)
${chalk.gray('-d, --dim')} Vector dimensions (default: 384)
${chalk.yellow('Examples:')}
${chalk.gray('# Run all benchmarks with 100k vectors')}
ruvector-pg bench run -t all -s 100000
${chalk.gray('# Run vector benchmark with 768 dimensions')}
ruvector-pg bench run -t vector -d 768
${chalk.gray('# Generate markdown report')}
ruvector-pg bench report -f markdown
`);
}
}
export default BenchmarkCommands;