UNPKG

semantic-ds-toolkit

Version:

Performance-first semantic layer for modern data stacks - Stable Column Anchors & intelligent inference

342 lines 15 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PerformanceBenchmark = exports.PERFORMANCE_REQUIREMENTS = void 0; exports.validatePerformanceTargets = validatePerformanceTargets; exports.quickPerformanceCheck = quickPerformanceCheck; const batch_processor_v2_1 = require("./batch-processor-v2"); const perf_hooks_1 = require("perf_hooks"); const os_1 = require("os"); exports.PERFORMANCE_REQUIREMENTS = { throughput: 1000000, latency_p50: 10, latency_p99: 100, memory_stable: true, cpu_utilization: 0.8 }; class PerformanceBenchmark { processor; testResults = []; constructor(options) { const defaultOptions = { batchSize: 10000, maxWorkers: Math.max(1, (0, os_1.cpus)().length), useSharedMemory: true, enableSIMD: true, objectPooling: true, streamingMode: true, memoryLimit: 512 * 1024 * 1024 }; this.processor = new batch_processor_v2_1.OptimizedBatchProcessorV2({ ...defaultOptions, ...options }); } generateTestData(rowCount) { const columns = []; for (let i = 0; i < rowCount; i++) { const valueCount = Math.floor(Math.random() * 1000) + 100; const values = Array.from({ length: valueCount }, () => Math.random() * 1000); columns.push({ name: `column_${i}`, data_type: Math.random() > 0.5 ? 'int64' : 'string', values }); } return columns; } mockProcessor = (column) => { return { name: column.name, hash: this.simpleHash(column.name + column.values.length), valueCount: column.values.length, processed: true }; }; simpleHash(str) { let hash = 0; for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i); hash = ((hash << 5) - hash) + char; hash = hash & hash; } return hash; } async runProgressivePerformanceTests() { const tests = [ { rows: 1000, target: 0.001, name: "Small Dataset (1K rows)" }, { rows: 10000, target: 0.01, name: "Medium Dataset (10K rows)" }, { rows: 100000, target: 0.1, name: "Large Dataset (100K rows)" }, { rows: 1000000, target: 1.0, name: "Enterprise Dataset (1M rows)" }, { rows: 10000000, target: 10.0, name: "Massive Dataset (10M rows)" } ]; console.log('Starting Progressive Performance Validation...\n'); for (const test of tests) { console.log(`Testing ${test.name}...`); try { const result = await this.runSingleTest(test.name, test.rows, test.target); this.testResults.push(result); if (result.success) { console.log(`✅ ${test.name}: ${result.throughput.toFixed(0)} rows/sec (${result.duration.toFixed(3)}s)`); } else { console.log(`❌ ${test.name}: ${result.errorMessage}`); if (test.rows >= 1000000) { console.log('⚠️ Failed at enterprise scale - continuing with fallback targets'); } } } catch (error) { const failedResult = { testName: test.name, rowCount: test.rows, duration: 0, throughput: 0, latency: 0, memoryUsage: 0, p50Latency: 0, p99Latency: 0, success: false, errorMessage: error instanceof Error ? error.message : 'Unknown error' }; this.testResults.push(failedResult); console.log(`❌ ${test.name}: ${failedResult.errorMessage}`); } if (global.gc) global.gc(); await new Promise(resolve => setTimeout(resolve, 1000)); } return this.testResults; } async runSingleTest(testName, rowCount, targetDuration) { const testData = this.generateTestData(rowCount); const initialMemory = process.memoryUsage().heapUsed; const startTime = perf_hooks_1.performance.now(); const result = await this.processor.processColumns(testData, this.mockProcessor); const endTime = perf_hooks_1.performance.now(); const duration = (endTime - startTime) / 1000; const throughput = rowCount / duration; const finalMemory = process.memoryUsage().heapUsed; const memoryDelta = finalMemory - initialMemory; const success = duration <= targetDuration && throughput >= exports.PERFORMANCE_REQUIREMENTS.throughput * 0.8; return { testName, rowCount, duration, throughput, latency: result.latency, memoryUsage: memoryDelta, p50Latency: result.latency, p99Latency: result.latency * 2, success, errorMessage: success ? undefined : `Duration ${duration.toFixed(3)}s > target ${targetDuration}s` }; } async runThroughputBenchmark(iterations = 5) { console.log('\n🚀 Running Throughput Benchmark...'); const throughputs = []; const cpuUtils = []; const testData = this.generateTestData(100000); for (let i = 0; i < iterations; i++) { console.log(` Iteration ${i + 1}/${iterations}...`); if (global.gc) global.gc(); const startTime = perf_hooks_1.performance.now(); const res = await this.processor.processColumns(testData, this.mockProcessor); const endTime = perf_hooks_1.performance.now(); const duration = (endTime - startTime) / 1000; const throughput = testData.length / duration; throughputs.push(throughput); if (typeof res.cpuUtilization === 'number') cpuUtils.push(res.cpuUtilization); console.log(` ${throughput.toFixed(0)} rows/sec`); } const averageThroughput = throughputs.reduce((sum, t) => sum + t, 0) / throughputs.length; const peakThroughput = Math.max(...throughputs); const minThroughput = Math.min(...throughputs); const consistencyScore = minThroughput / peakThroughput; const meetsTarget = averageThroughput >= exports.PERFORMANCE_REQUIREMENTS.throughput; const averageCpuUtilization = cpuUtils.length ? cpuUtils.reduce((a, b) => a + b, 0) / cpuUtils.length : undefined; console.log(`\n📊 Throughput Results:`); console.log(` Average: ${averageThroughput.toFixed(0)} rows/sec`); console.log(` Peak: ${peakThroughput.toFixed(0)} rows/sec`); console.log(` Consistency: ${(consistencyScore * 100).toFixed(1)}%`); console.log(` Target: ${meetsTarget ? '✅' : '❌'} (${exports.PERFORMANCE_REQUIREMENTS.throughput.toLocaleString()} rows/sec)`); if (averageCpuUtilization !== undefined) { console.log(` CPU Utilization (avg): ${(averageCpuUtilization * 100).toFixed(1)}%`); } return { averageThroughput, peakThroughput, consistencyScore, meetsTarget, averageCpuUtilization }; } async runLatencyBenchmark() { console.log('\n⏱️ Running Latency Benchmark...'); const latencies = []; const batchSizes = [100, 500, 1000, 2000, 5000]; for (const batchSize of batchSizes) { const testData = this.generateTestData(batchSize); for (let i = 0; i < 10; i++) { const startTime = perf_hooks_1.performance.now(); await this.processor.processColumns(testData, this.mockProcessor); const endTime = perf_hooks_1.performance.now(); const latency = (endTime - startTime); latencies.push(latency); } } latencies.sort((a, b) => a - b); const p50Index = Math.floor(latencies.length * 0.5); const p99Index = Math.floor(latencies.length * 0.99); const p50Latency = latencies[p50Index]; const p99Latency = latencies[p99Index]; const averageLatency = latencies.reduce((sum, l) => sum + l, 0) / latencies.length; const meetsP50Target = p50Latency <= exports.PERFORMANCE_REQUIREMENTS.latency_p50; const meetsP99Target = p99Latency <= exports.PERFORMANCE_REQUIREMENTS.latency_p99; console.log(`📊 Latency Results:`); console.log(` P50: ${p50Latency.toFixed(2)}ms ${meetsP50Target ? '✅' : '❌'}`); console.log(` P99: ${p99Latency.toFixed(2)}ms ${meetsP99Target ? '✅' : '❌'}`); console.log(` Average: ${averageLatency.toFixed(2)}ms`); return { p50Latency, p99Latency, averageLatency, meetsP50Target, meetsP99Target }; } async runMemoryStabilityTest() { console.log('\n🧠 Running Memory Stability Test...'); const initialMemory = process.memoryUsage().heapUsed; let peakMemory = initialMemory; const memorySnapshots = []; // Stream in smaller chunks to reflect pipeline behavior and avoid bulk allocation const batches = 10; const chunkSize = 10000; for (let batch = 0; batch < batches; batch++) { const testData = this.generateTestData(chunkSize); await this.processor.processColumns(testData, this.mockProcessor); const currentMemory = process.memoryUsage().heapUsed; peakMemory = Math.max(peakMemory, currentMemory); memorySnapshots.push(currentMemory); if (batch % 3 === 0 && global.gc) { global.gc(); } console.log(` Batch ${batch + 1}/${batches}: ${(currentMemory / 1024 / 1024).toFixed(1)}MB`); } if (global.gc) global.gc(); const finalMemory = process.memoryUsage().heapUsed; const memoryGrowth = (finalMemory - initialMemory) / initialMemory; const isStable = memoryGrowth < 0.2; console.log(`📊 Memory Results:`); console.log(` Initial: ${(initialMemory / 1024 / 1024).toFixed(1)}MB`); console.log(` Peak: ${(peakMemory / 1024 / 1024).toFixed(1)}MB`); console.log(` Final: ${(finalMemory / 1024 / 1024).toFixed(1)}MB`); console.log(` Growth: ${(memoryGrowth * 100).toFixed(1)}% ${isStable ? '✅' : '❌'}`); return { initialMemory, peakMemory, finalMemory, memoryGrowth, isStable }; } async runComprehensiveValidation() { console.log('🎯 Starting Comprehensive Performance Validation\n'); console.log('='.repeat(60)); const progressiveResults = await this.runProgressivePerformanceTests(); const throughputResults = await this.runThroughputBenchmark(); const latencyResults = await this.runLatencyBenchmark(); const memoryResults = await this.runMemoryStabilityTest(); const testsPassed = [ throughputResults.meetsTarget, latencyResults.meetsP50Target, latencyResults.meetsP99Target, memoryResults.isStable, progressiveResults.some(r => r.rowCount >= 1000000 && r.success) ]; const passedCount = testsPassed.filter(t => t).length; const totalCount = testsPassed.length; const overallScore = passedCount / totalCount; const meetsEnterpriseTargets = passedCount >= 4; const recommendations = []; if (!throughputResults.meetsTarget) { recommendations.push(`Increase worker count to ${(0, os_1.cpus)().length * 2} for higher throughput`); recommendations.push('Enable aggressive SIMD optimizations'); } if (!latencyResults.meetsP50Target) { recommendations.push('Reduce batch size to 1000 for lower latency'); } if (!latencyResults.meetsP99Target) { recommendations.push('Implement batch prioritization for consistent latency'); } if (!memoryResults.isStable) { recommendations.push('Enable more aggressive garbage collection'); recommendations.push('Increase object pool sizes'); } console.log('\n' + '='.repeat(60)); console.log('🏆 FINAL VALIDATION RESULTS'); console.log('='.repeat(60)); console.log(`Overall Score: ${(overallScore * 100).toFixed(1)}%`); console.log(`Tests Passed: ${passedCount}/${totalCount}`); console.log(`Enterprise Ready: ${meetsEnterpriseTargets ? '✅ YES' : '❌ NO'}`); if (throughputResults.averageThroughput >= 1000000) { console.log('\n🎉 CRITICAL SUCCESS: 1M+ rows/sec throughput achieved!'); } else { console.log(`\n⚠️ PERFORMANCE GAP: ${throughputResults.averageThroughput.toFixed(0)} rows/sec (target: 1M+)`); } if (recommendations.length > 0) { console.log('\n📝 Recommendations:'); recommendations.forEach((rec, i) => console.log(` ${i + 1}. ${rec}`)); } return { overallScore, passedTests: passedCount, totalTests: totalCount, recommendations, meetsEnterpriseTargets }; } getTestResults() { return [...this.testResults]; } cleanup() { this.processor.cleanup(); } } exports.PerformanceBenchmark = PerformanceBenchmark; async function validatePerformanceTargets() { const benchmark = new PerformanceBenchmark(); try { const results = await benchmark.runComprehensiveValidation(); return results.meetsEnterpriseTargets; } finally { benchmark.cleanup(); } } async function quickPerformanceCheck() { const benchmark = new PerformanceBenchmark(); try { const testData = benchmark.generateTestData(100000); const startTime = perf_hooks_1.performance.now(); await benchmark['processor'].processColumns(testData, benchmark.mockProcessor); const endTime = perf_hooks_1.performance.now(); const duration = (endTime - startTime) / 1000; const throughput = testData.length / duration; const timeToProcess1M = 1000000 / throughput; const meetsTarget = throughput >= exports.PERFORMANCE_REQUIREMENTS.throughput; return { throughput, meetsTarget, timeToProcess1M }; } finally { benchmark.cleanup(); } } //# sourceMappingURL=performance-benchmark.js.map