UNPKG

@algochad/prisma-core

Version:

A comprehensive NestJS library that provides EF-Core-like operations using Prisma and GraphQL. Features LINQ-style query builders, advanced data manipulation, GraphQL integration with genql, and a unified API for both Prisma and GraphQL operations. Includ

783 lines โ€ข 40.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BenchmarkUtils = void 0; const perf_hooks_1 = require("perf_hooks"); const async_enumerable_1 = require("./collections/linq/async-enumerable"); const enumerable_1 = require("./collections/linq/enumerable"); class BenchmarkUtils { static async measureTime(operation, operationName = 'operation') { try { const memoryBefore = process.memoryUsage ? process.memoryUsage().heapUsed : 0; const startTime = perf_hooks_1.performance.now(); const result = await operation(); const endTime = perf_hooks_1.performance.now(); const time = endTime - startTime; const memoryAfter = process.memoryUsage ? process.memoryUsage().heapUsed : 0; const memoryUsage = Math.max(0, memoryAfter - memoryBefore); console.log(`${operationName} completed in ${time.toFixed(2)}ms (Memory: ${(memoryUsage / 1024 / 1024).toFixed(2)}MB)`); return { time, result, memoryUsage }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); console.error(`${operationName} failed:`, errorMessage); return { time: -1, result: null, error: errorMessage }; } } static generateTestData(size) { return Array.from({ length: size }, (_, i) => ({ id: i + 1, value: Math.random() * 1000, name: `Item_${i + 1}`, isActive: Math.random() > 0.3, })); } static complexComputation(item) { let result = item.value; for (let i = 0; i < 1000; i++) { result = Math.sqrt(result * Math.sin(result) + Math.cos(result)); } return result; } static async asyncComputation(item) { return Promise.resolve(BenchmarkUtils.complexComputation(item)); } static async runComprehensiveBenchmark(dataSize = 10000) { console.log(`\n๐Ÿš€ Starting Comprehensive Collection Benchmark (Data Size: ${dataSize})\n`); const results = []; console.log('๐Ÿ“Š Testing Filter Operations...'); const filterData = BenchmarkUtils.generateTestData(dataSize); const filterResult = await BenchmarkUtils.benchmarkOperation('Filter (isActive = true)', filterData, (enumerable) => enumerable.Where((x) => x.isActive).ToArray(), async (asyncEnumerable) => await asyncEnumerable.Where((x) => x.isActive).ToArrayAsync()); results.push(filterResult); console.log('๐Ÿ“Š Testing Map Operations...'); const mapData = BenchmarkUtils.generateTestData(dataSize); const mapResult = await BenchmarkUtils.benchmarkOperation('Map (transform to string)', mapData, (enumerable) => enumerable .Select((x) => `${x.name}_${x.value.toFixed(2)}`) .ToArray(), async (asyncEnumerable) => await asyncEnumerable .Select((x) => `${x.name}_${x.value.toFixed(2)}`) .ToArrayAsync()); results.push(mapResult); console.log('๐Ÿ“Š Testing Complex Computation...'); const computationData = BenchmarkUtils.generateTestData(Math.min(1000, dataSize)); const computationResult = await BenchmarkUtils.benchmarkOperation('Complex Computation', computationData, (enumerable) => enumerable .Select((x) => BenchmarkUtils.complexComputation(x)) .ToArray(), async (asyncEnumerable) => await asyncEnumerable .Select(async (x) => await BenchmarkUtils.asyncComputation(x)) .ToArrayAsync()); results.push(computationResult); console.log('๐Ÿ“Š Testing Aggregation Operations...'); const aggregationData = BenchmarkUtils.generateTestData(dataSize); const aggregationResult = await BenchmarkUtils.benchmarkOperation('Sum of values', aggregationData, (enumerable) => enumerable.Sum((x) => x?.value), async (asyncEnumerable) => await asyncEnumerable.SumAsync((x) => x.value)); results.push(aggregationResult); console.log('๐Ÿ“Š Testing Count Operations...'); const countData = BenchmarkUtils.generateTestData(dataSize); const countResult = await BenchmarkUtils.benchmarkOperation('Count active items', countData, (enumerable) => enumerable.Count((x) => x.isActive), async (asyncEnumerable) => await asyncEnumerable.CountAsync((x) => x.isActive)); results.push(countResult); console.log('๐Ÿ“Š Testing First/Any Operations...'); const firstData = BenchmarkUtils.generateTestData(dataSize); const firstResult = await BenchmarkUtils.benchmarkOperation('Find first active item', firstData, (enumerable) => enumerable.FirstOrDefault((x) => x.isActive), async (asyncEnumerable) => await asyncEnumerable.FirstOrDefaultAsync((x) => x.isActive)); results.push(firstResult); console.log('๐Ÿ“Š Testing Sorting Operations...'); const sortingData = BenchmarkUtils.generateTestData(dataSize); const sortingResult = await BenchmarkUtils.benchmarkOperation('Sort by value (ascending)', sortingData, (enumerable) => enumerable.OrderBy((x) => x.value).ToArray(), async (asyncEnumerable) => await asyncEnumerable.OrderBy((x) => x.value).ToArrayAsync()); results.push(sortingResult); console.log('๐Ÿ“Š Testing Filtering + Sorting Operations...'); const filteringSortingData = BenchmarkUtils.generateTestData(dataSize); const filteringSortingResult = await BenchmarkUtils.benchmarkOperation('Filter (isActive = true) + Sort by value (ascending)', filteringSortingData, (enumerable) => enumerable .Where((x) => x.isActive) .OrderBy((x) => x.value) .ToArray(), async (asyncEnumerable) => await asyncEnumerable .Where((x) => x.isActive) .OrderBy((x) => x.value) .ToArrayAsync()); results.push(filteringSortingResult); console.log('๐Ÿ“Š Testing Distinct Operations...'); const distinctData = BenchmarkUtils.generateTestData(dataSize); const distinctResult = await BenchmarkUtils.benchmarkOperation('Distinct by name prefix', distinctData, (enumerable) => enumerable.DistinctBy((x) => x.name.substring(0, 5)).ToArray(), async (asyncEnumerable) => await asyncEnumerable .Distinct((x) => x.name.substring(0, 5)) .ToArrayAsync()); results.push(distinctResult); console.log('๐Ÿ“Š Testing Complex Chaining Operations...'); const complexChainData = BenchmarkUtils.generateTestData(dataSize); const complexChainResult = await BenchmarkUtils.benchmarkOperation('Complex Chain: Filter + Map + Sort + Take', complexChainData, (enumerable) => enumerable .Where((x) => x.isActive && x.value > 100) .Select((x) => ({ ...x, computed: x.value * 2 + x.id })) .OrderByDescending((x) => x.computed) .Take(50) .ToArray(), async (asyncEnumerable) => await asyncEnumerable .Where((x) => x.isActive && x.value > 100) .Select((x) => ({ ...x, computed: x.value * 2 + x.id })) .OrderByDescending((x) => x.computed) .Take(50) .ToArrayAsync()); results.push(complexChainResult); console.log('๐Ÿ“Š Testing Skip/Take Operations...'); const paginationData = BenchmarkUtils.generateTestData(dataSize); const paginationResult = await BenchmarkUtils.benchmarkOperation('Pagination: Skip(100) + Take(50)', paginationData, (enumerable) => enumerable.Skip(100).Take(50).ToArray(), async (asyncEnumerable) => await asyncEnumerable.Skip(100).Take(50).ToArrayAsync()); results.push(paginationResult); console.log('๐Ÿ“Š Testing Min/Max Operations...'); const minMaxData = BenchmarkUtils.generateTestData(dataSize); const minMaxResult = await BenchmarkUtils.benchmarkOperation('Find Min/Max values', minMaxData, (enumerable) => ({ min: enumerable.Min((x) => x.value), max: enumerable.Max((x) => x.value), }), async (asyncEnumerable) => ({ min: await asyncEnumerable.MinAsync((x) => x.value), max: await asyncEnumerable.MaxAsync((x) => x.value), })); results.push(minMaxResult); console.log('๐Ÿ“Š Testing Edge Cases...'); const emptyResult = await BenchmarkUtils.benchmarkOperation('Empty Collection Processing', [], (enumerable) => enumerable.Where((x) => x.isActive).ToArray(), async (asyncEnumerable) => await asyncEnumerable .Where((x) => x.isActive) .ToArrayAsync()); results.push(emptyResult); if (dataSize >= 5000) { const largeSubsetData = BenchmarkUtils.generateTestData(1000); const largeSubsetResult = await BenchmarkUtils.benchmarkOperation('Large Subset Processing (Top 1000 items)', largeSubsetData, (enumerable) => enumerable .Where((x) => x.isActive) .OrderBy((x) => x.value) .Select((x) => ({ id: x.id, name: x.name, category: 'processed', })) .ToArray(), async (asyncEnumerable) => await asyncEnumerable .Where((x) => x.isActive) .OrderBy((x) => x.value) .Select((x) => ({ id: x.id, name: x.name, category: 'processed', })) .ToArrayAsync()); results.push(largeSubsetResult); } console.log('๐Ÿ“Š Testing Group By Operations...'); const groupByData = BenchmarkUtils.generateTestData(Math.min(1000, dataSize)); const groupByResult = await BenchmarkUtils.benchmarkOperation('Group by active status', groupByData, (enumerable) => { const grouped = enumerable.GroupBy((x) => x.isActive ? 'active' : 'inactive'); return grouped.ToArray(); }, async (asyncEnumerable) => { const allItems = await asyncEnumerable.ToArrayAsync(); const activeItems = allItems.filter((x) => x.isActive); const inactiveItems = allItems.filter((x) => !x.isActive); return [ { key: 'active', items: activeItems }, { key: 'inactive', items: inactiveItems }, ]; }); results.push(groupByResult); const synchronousTotal = results.reduce((sum, r) => sum + (r.synchronous.time > 0 ? r.synchronous.time : 0), 0); const asynchronousTotal = results.reduce((sum, r) => sum + (r.asynchronous.time > 0 ? r.asynchronous.time : 0), 0); const asyncSpeedup = synchronousTotal > 0 ? `${(synchronousTotal / asynchronousTotal).toFixed(2)}x` : 'N/A'; const summary = { testDataSize: dataSize, cpuCount: require('os').cpus().length, results, summary: { synchronousTotal, asynchronousTotal, asyncSpeedup, }, }; BenchmarkUtils.printBenchmarkSummary(summary); return summary; } static async benchmarkOperation(operationName, testData, syncOperation, asyncOperation) { const enumerable = new enumerable_1.Enumerable(testData); const asyncEnumerable = async_enumerable_1.AsyncEnumerable.fromArray(testData); const syncResult = await BenchmarkUtils.measureTime(() => { return syncOperation(enumerable); }, `${operationName} (Sync)`); const asyncResult = await BenchmarkUtils.measureTime(async () => { return await asyncOperation(asyncEnumerable); }, `${operationName} (Async)`); const performanceRatio = syncResult.time > 0 && asyncResult.time > 0 ? syncResult.time / asyncResult.time : 1; const recommendation = performanceRatio > 1.1 ? 'async' : performanceRatio < 0.9 ? 'sync' : 'neutral'; return { operation: operationName, category: 'general', dataSize: testData.length, synchronous: { time: syncResult.time, result: syncResult.result, error: syncResult.error, memoryUsed: syncResult.memoryUsage, }, asynchronous: { time: asyncResult.time, result: asyncResult.result, error: asyncResult.error, memoryUsed: asyncResult.memoryUsage, }, performanceRatio, recommendation, }; } static printBenchmarkSummary(summary) { console.log('\n' + '='.repeat(100)); console.log('๐Ÿ† BENCHMARK SUMMARY'); console.log('='.repeat(100)); console.log(`๐Ÿ“Š Test Data Size: ${summary.testDataSize.toLocaleString()} items`); console.log(`๐Ÿ’ป CPU Cores: ${summary.cpuCount}`); console.log('='.repeat(100)); console.log('\n๐Ÿ“ˆ DETAILED RESULTS:'); console.log('-'.repeat(100)); console.log('Operation'.padEnd(35) + 'Sync (ms)'.padEnd(12) + 'Async (ms)'.padEnd(12) + 'Ratio'.padEnd(8) + 'Best'.padEnd(12) + 'Recommendation'); console.log('-'.repeat(100)); summary.results.forEach((result) => { const syncTime = result.synchronous.time > 0 ? result.synchronous.time.toFixed(2) : 'ERROR'; const asyncTime = result.asynchronous.time > 0 ? result.asynchronous.time.toFixed(2) : 'ERROR'; const times = [ { name: 'Sync', time: result.synchronous.time }, { name: 'Async', time: result.asynchronous.time }, ].filter((t) => t.time > 0); const best = times.length > 0 ? times.reduce((min, current) => current.time < min.time ? current : min).name : 'N/A'; const ratio = result.performanceRatio ? result.performanceRatio.toFixed(2) : 'N/A'; const recommendation = result.recommendation ? result.recommendation === 'async' ? 'โšก Async' : result.recommendation === 'sync' ? '๐Ÿ”„ Sync' : 'โš–๏ธ Either' : 'N/A'; const bestFormatted = best !== 'N/A' ? `๐Ÿ† ${best}` : 'N/A'; const truncatedOperation = result.operation.length > 32 ? result.operation.substring(0, 29) + '...' : result.operation; console.log(truncatedOperation.padEnd(35) + syncTime.padEnd(12) + asyncTime.padEnd(12) + ratio.padEnd(8) + bestFormatted.padEnd(12) + recommendation); }); console.log('-'.repeat(100)); console.log('-'.repeat(110)); console.log('\n๐Ÿ”ฅ PERFORMANCE SUMMARY:'); console.log(`โšก Total Synchronous Time: ${summary.summary.synchronousTotal.toFixed(2)}ms`); console.log(`๐Ÿ”„ Total Asynchronous Time: ${summary.summary.asynchronousTotal.toFixed(2)}ms`); console.log(`๐Ÿ“ˆ Async Speedup: ${summary.summary.asyncSpeedup}`); console.log('='.repeat(100)); console.log('\n๐Ÿ’ก RECOMMENDATIONS:'); console.log('-'.repeat(100)); const syncWins = summary.results.filter((r) => r.recommendation === 'sync').length; const asyncWins = summary.results.filter((r) => r.recommendation === 'async').length; const neutrals = summary.results.filter((r) => r.recommendation === 'neutral').length; console.log(`๐Ÿ“Š Performance Analysis:`); console.log(` โ€ข Synchronous wins: ${syncWins} operations`); console.log(` โ€ข Asynchronous wins: ${asyncWins} operations`); console.log(` โ€ข Neutral performance: ${neutrals} operations`); const avgSyncMemory = summary.results .filter((r) => r.synchronous.memoryUsed && r.synchronous.memoryUsed > 0) .reduce((sum, r) => sum + (r.synchronous.memoryUsed || 0), 0) / summary.results.length; const avgAsyncMemory = summary.results .filter((r) => r.asynchronous.memoryUsed && r.asynchronous.memoryUsed > 0) .reduce((sum, r) => sum + (r.asynchronous.memoryUsed || 0), 0) / summary.results.length; if (avgSyncMemory > 0 || avgAsyncMemory > 0) { console.log(`\n๐Ÿง  Memory Usage Analysis:`); console.log(` โ€ข Average Sync Memory: ${(avgSyncMemory / 1024 / 1024).toFixed(2)}MB`); console.log(` โ€ข Average Async Memory: ${(avgAsyncMemory / 1024 / 1024).toFixed(2)}MB`); } console.log(`\n๐ŸŽฏ Overall Recommendations:`); if (asyncWins > syncWins) { console.log('โœ… Asynchronous processing shows better performance for most operations'); console.log('๐Ÿ’ก Consider using AsyncEnumerable for CPU-intensive workloads'); } else if (syncWins > asyncWins) { console.log('โœ… Synchronous processing shows better performance for most operations'); console.log('๐Ÿ’ก Consider using Enumerable for simple, fast operations'); } else { console.log('โš–๏ธ Performance is balanced between sync and async approaches'); console.log('๐Ÿ’ก Choose based on your specific use case and data size'); } if (summary.summary.asynchronousTotal < summary.summary.synchronousTotal) { console.log('๐Ÿš€ Asynchronous processing shows overall performance benefits'); } console.log(`๐Ÿ† Best overall approach: ${summary.summary.asynchronousTotal < summary.summary.synchronousTotal ? 'Asynchronous' : 'Synchronous'} processing`); console.log('='.repeat(100) + '\n'); } static async quickBenchmark(dataSize = 1000) { console.log(`\nโšก Quick Benchmark (${dataSize} items)\n`); const testData = BenchmarkUtils.generateTestData(dataSize); const result = await BenchmarkUtils.benchmarkOperation('Filter + Map', testData, (enumerable) => enumerable .Where((x) => x.isActive) .Select((x) => x.value * 2) .ToArray(), async (asyncEnumerable) => await asyncEnumerable .Where(async (x) => x.isActive) .Select(async (x) => x.value * 2) .ToArrayAsync()); console.log(`Sync: ${result.synchronous.time.toFixed(2)}ms`); console.log(`Async: ${result.asynchronous.time.toFixed(2)}ms`); const best = [ { name: 'Synchronous', time: result.synchronous.time }, { name: 'Asynchronous', time: result.asynchronous.time }, ] .filter((r) => r.time > 0) .reduce((min, current) => current.time < min.time ? current : min); console.log(`๐Ÿ† Winner: ${best.name} (${best.time.toFixed(2)}ms)\n`); } static async runStressTest(sizes = [1000, 5000, 10000, 50000]) { console.log('\n๐Ÿ”ฅ Starting Performance Stress Test\n'); console.log('='.repeat(80)); for (const size of sizes) { console.log(`\n๐Ÿ“Š Testing with ${size.toLocaleString()} items:`); console.log('-'.repeat(40)); const filterTestData = BenchmarkUtils.generateTestData(size); const filterResult = await BenchmarkUtils.benchmarkOperation(`Filter (${size} items)`, filterTestData, (enumerable) => enumerable.Where((x) => x.isActive).ToArray(), async (asyncEnumerable) => await asyncEnumerable .Where((x) => x.isActive) .ToArrayAsync()); const sortTestData = BenchmarkUtils.generateTestData(size); const sortResult = await BenchmarkUtils.benchmarkOperation(`Sort (${size} items)`, sortTestData, (enumerable) => enumerable.OrderBy((x) => x.value).ToArray(), async (asyncEnumerable) => await asyncEnumerable .OrderBy((x) => x.value) .ToArrayAsync()); console.log(` Filter - Sync: ${filterResult.synchronous.time.toFixed(2)}ms, Async: ${filterResult.asynchronous.time.toFixed(2)}ms`); console.log(` Sort - Sync: ${sortResult.synchronous.time.toFixed(2)}ms, Async: ${sortResult.asynchronous.time.toFixed(2)}ms`); } console.log('\n='.repeat(80)); console.log('๐Ÿ Stress Test Complete'); } static async runScalabilityTest(startSize = 1000, endSize = 10000, steps = 5) { console.log('\n๐Ÿ“ˆ Starting Scalability Analysis\n'); console.log('='.repeat(80)); const stepSize = Math.floor((endSize - startSize) / (steps - 1)); const results = []; for (let i = 0; i < steps; i++) { const size = startSize + i * stepSize; console.log(`\n๐Ÿ” Testing scalability with ${size.toLocaleString()} items:`); const testData = BenchmarkUtils.generateTestData(size); const result = await BenchmarkUtils.benchmarkOperation(`Complex Chain (${size} items)`, testData, (enumerable) => enumerable .Where((x) => x.isActive) .Select((x) => ({ ...x, computed: x.value * 2 })) .OrderBy((x) => x.computed) .Take(Math.min(100, size)) .ToArray(), async (asyncEnumerable) => await asyncEnumerable .Where((x) => x.isActive) .Select((x) => ({ ...x, computed: x.value * 2 })) .OrderBy((x) => x.computed) .Take(Math.min(100, size)) .ToArrayAsync()); results.push({ size, syncTime: result.synchronous.time, asyncTime: result.asynchronous.time, }); console.log(` Sync: ${result.synchronous.time.toFixed(2)}ms`); console.log(` Async: ${result.asynchronous.time.toFixed(2)}ms`); } console.log('\n๐Ÿ“Š Scalability Summary:'); console.log('-'.repeat(60)); console.log('Size'.padEnd(15) + 'Sync (ms)'.padEnd(15) + 'Async (ms)'.padEnd(15) + 'Ratio'); console.log('-'.repeat(60)); results.forEach((result) => { const ratio = result.syncTime / result.asyncTime; console.log(result.size.toLocaleString().padEnd(15) + result.syncTime.toFixed(2).padEnd(15) + result.asyncTime.toFixed(2).padEnd(15) + ratio.toFixed(2)); }); console.log('='.repeat(80)); } static async runEdgeCaseTests() { console.log('\n๐Ÿงช Starting Edge Case Tests\n'); console.log('='.repeat(80)); console.log('๐Ÿ” Testing empty collections...'); const emptyTest = await BenchmarkUtils.benchmarkOperation('Empty Collection', [], (enumerable) => enumerable.Where((x) => x.isActive).ToArray(), async (asyncEnumerable) => await asyncEnumerable .Where((x) => x.isActive) .ToArrayAsync()); console.log(` Empty - Sync: ${emptyTest.synchronous.time.toFixed(2)}ms, Async: ${emptyTest.asynchronous.time.toFixed(2)}ms`); console.log('๐Ÿ” Testing single item...'); const singleItemData = BenchmarkUtils.generateTestData(1); const singleTest = await BenchmarkUtils.benchmarkOperation('Single Item', singleItemData, (enumerable) => enumerable.Where((x) => x.isActive).ToArray(), async (asyncEnumerable) => await asyncEnumerable.Where((x) => x.isActive).ToArrayAsync()); console.log(` Single - Sync: ${singleTest.synchronous.time.toFixed(2)}ms, Async: ${singleTest.asynchronous.time.toFixed(2)}ms`); console.log('๐Ÿ” Testing all items match...'); const allMatchData = Array.from({ length: 1000 }, (_, i) => ({ id: i + 1, value: Math.random() * 1000, name: `Item_${i + 1}`, isActive: true, })); const allMatchTest = await BenchmarkUtils.benchmarkOperation('All Items Match', allMatchData, (enumerable) => enumerable.Where((x) => x.isActive).ToArray(), async (asyncEnumerable) => await asyncEnumerable.Where((x) => x.isActive).ToArrayAsync()); console.log(` All Match - Sync: ${allMatchTest.synchronous.time.toFixed(2)}ms, Async: ${allMatchTest.asynchronous.time.toFixed(2)}ms`); console.log('๐Ÿ” Testing no items match...'); const noMatchData = Array.from({ length: 1000 }, (_, i) => ({ id: i + 1, value: Math.random() * 1000, name: `Item_${i + 1}`, isActive: false, })); const noMatchTest = await BenchmarkUtils.benchmarkOperation('No Items Match', noMatchData, (enumerable) => enumerable.Where((x) => x.isActive).ToArray(), async (asyncEnumerable) => await asyncEnumerable.Where((x) => x.isActive).ToArrayAsync()); console.log(` No Match - Sync: ${noMatchTest.synchronous.time.toFixed(2)}ms, Async: ${noMatchTest.asynchronous.time.toFixed(2)}ms`); console.log('\n='.repeat(80)); console.log('๐Ÿ Edge Case Tests Complete'); } static async runFullBenchmarkSuite(dataSize = 10000) { console.log('\n๐Ÿš€ Starting Full Benchmark Suite\n'); console.log('='.repeat(80)); console.log(`๐Ÿ“Š Data Size: ${dataSize.toLocaleString()} items`); console.log(`๐Ÿ’ป CPU Cores: ${require('os').cpus().length}`); console.log(`๐Ÿ•’ Start Time: ${new Date().toISOString()}`); console.log('='.repeat(80)); try { console.log('\n๐Ÿ”ฌ Phase 1: Comprehensive Benchmark'); const comprehensiveResults = await BenchmarkUtils.runComprehensiveBenchmark(dataSize); console.log('\n๐Ÿ”ฅ Phase 2: Stress Testing'); await BenchmarkUtils.runStressTest([1000, 5000, dataSize]); console.log('\n๐Ÿ“ˆ Phase 3: Scalability Analysis'); await BenchmarkUtils.runScalabilityTest(1000, dataSize, 5); console.log('\n๐Ÿงช Phase 4: Edge Case Testing'); await BenchmarkUtils.runEdgeCaseTests(); console.log('\n๐Ÿ“‹ Final Summary Report'); console.log('='.repeat(80)); console.log(`๐Ÿ•’ End Time: ${new Date().toISOString()}`); console.log(`โœ… Total Operations Tested: ${comprehensiveResults.results.length}`); console.log(`๐Ÿ† Overall Performance: ${comprehensiveResults.summary.asyncSpeedup} async speedup`); const successfulTests = comprehensiveResults.results.filter((r) => !r.synchronous.error && !r.asynchronous.error).length; console.log(`โœ”๏ธ Successful Tests: ${successfulTests}/${comprehensiveResults.results.length}`); if (successfulTests < comprehensiveResults.results.length) { const failedTests = comprehensiveResults.results.length - successfulTests; console.log(`โŒ Failed Tests: ${failedTests}`); } console.log('='.repeat(80)); console.log('๐ŸŽ‰ Full Benchmark Suite Complete!'); } catch (error) { console.error('\nโŒ Benchmark Suite Failed:', error); throw error; } } static async benchmarkCustomOperation(operation, config = {}) { const { iterations = 10, warmupRuns = 3, trackMemory = true, showProgress = false, timeout = 30000, } = config; if (showProgress) { console.log(`๐Ÿ”ง Benchmarking "${operation.name}" (${iterations} iterations)...`); } for (let i = 0; i < warmupRuns; i++) { try { await operation.operation(operation.input); } catch (error) { } } const times = []; let memoryUsed = 0; let result; let error; try { for (let i = 0; i < iterations; i++) { if (showProgress && iterations > 10) { process.stdout.write(`\r Progress: ${i + 1}/${iterations}`); } const memoryBefore = trackMemory && process.memoryUsage ? process.memoryUsage().heapUsed : 0; const startTime = perf_hooks_1.performance.now(); result = await Promise.race([ operation.operation(operation.input), new Promise((_, reject) => setTimeout(() => reject(new Error('Operation timed out')), timeout)), ]); const endTime = perf_hooks_1.performance.now(); const memoryAfter = trackMemory && process.memoryUsage ? process.memoryUsage().heapUsed : 0; times.push(endTime - startTime); if (trackMemory) { memoryUsed += Math.max(0, memoryAfter - memoryBefore); } } if (showProgress && iterations > 10) { console.log(); } } catch (err) { error = err instanceof Error ? err.message : String(err); } const averageTime = times.length > 0 ? times.reduce((a, b) => a + b, 0) / times.length : 0; const totalTime = times.reduce((a, b) => a + b, 0); return { operationName: operation.name, averageTime, totalTime, iterations: times.length, memoryUsed: trackMemory ? memoryUsed / iterations : undefined, result: result, error, }; } static async benchmarkOperationsBatch(operations, config = {}) { const { showProgress = false } = config; if (showProgress) { console.log(`๐Ÿ“Š Running batch benchmark with ${operations.length} operations...`); } const results = await Promise.all(operations.map(async (operation, index) => { if (showProgress) { console.log(`\n ${index + 1}/${operations.length}: ${operation.name}`); } const result = await this.benchmarkCustomOperation(operation, { ...config, showProgress: false, }); return { name: operation.name, time: result.averageTime, result: result.result, error: result.error, memoryUsed: result.memoryUsed, iterations: result.iterations, }; })); const validResults = results.filter((r) => !r.error && r.time > 0); if (validResults.length === 0) { throw new Error('No valid benchmark results obtained'); } const fastest = validResults.reduce((min, current) => current.time < min.time ? current : min); const slowest = validResults.reduce((max, current) => current.time > max.time ? current : max); const averageTime = validResults.reduce((sum, r) => sum + r.time, 0) / validResults.length; const totalTime = validResults.reduce((sum, r) => sum + r.time, 0); return { operations: results, summary: { fastest: fastest.name, slowest: slowest.name, averageTime, totalTime, }, }; } static async benchmarkQuery(queryOperation, dataGenerator, options = {}) { const { dataSizes = [100, 500, 1000, 5000, 10000], iterations = 5, warmupRuns = 2, trackMemory = true, scalabilityAnalysis = true, } = options; console.log(`๐Ÿ” Query scalability analysis with data sizes: ${dataSizes.join(', ')}`); const results = []; for (const size of dataSizes) { console.log(` Testing with ${size.toLocaleString()} items...`); const testData = dataGenerator(size); const operation = { name: `Query (${size} items)`, operation: queryOperation, input: testData, iterations, warmupRuns, }; const benchmark = await this.benchmarkCustomOperation(operation, { iterations, warmupRuns, trackMemory, showProgress: false, }); results.push({ dataSize: size, time: benchmark.averageTime, memoryUsed: benchmark.memoryUsed, result: benchmark.result, error: benchmark.error, }); } let analysis; if (scalabilityAnalysis && results.length >= 3) { const validResults = results.filter((r) => !r.error && r.time > 0); if (validResults.length >= 3) { const n = validResults.length; const sumX = validResults.reduce((sum, r) => sum + r.dataSize, 0); const sumY = validResults.reduce((sum, r) => sum + r.time, 0); const sumXY = validResults.reduce((sum, r) => sum + r.dataSize * r.time, 0); const sumX2 = validResults.reduce((sum, r) => sum + r.dataSize * r.dataSize, 0); const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX); const correlation = slope > 0 ? Math.min(slope / 1000, 1) : 0; let timeComplexity = 'Unknown'; let recommendation = 'Monitor performance with larger datasets'; if (correlation > 0.8) { timeComplexity = 'Linear O(n)'; recommendation = 'Performance scales linearly with data size'; } else if (correlation > 0.5) { timeComplexity = 'Sub-linear or variable'; recommendation = 'Consider optimizations for large datasets'; } else { timeComplexity = 'Constant or very efficient'; recommendation = 'Excellent scalability characteristics'; } analysis = { timeComplexity, recommendation, linearFit: correlation, }; } } return { operation: 'Query Scalability Test', results, scalabilityAnalysis: analysis, }; } static async compareOperations(operation1, operation2, input, config = {}) { console.log(`โš”๏ธ Comparing: "${operation1.name}" vs "${operation2.name}"`); const op1Config = { name: operation1.name, operation: operation1.operation, input, }; const op2Config = { name: operation2.name, operation: operation2.operation, input, }; const [result1, result2] = await Promise.all([ this.benchmarkCustomOperation(op1Config, config), this.benchmarkCustomOperation(op2Config, config), ]); const timeDifference = Math.abs(result1.averageTime - result2.averageTime); const performanceRatio = result1.averageTime / result2.averageTime; let fasterOperation; let recommendation; if (performanceRatio > 1.1) { fasterOperation = operation2.name; recommendation = `${operation2.name} is ${performanceRatio.toFixed(2)}x faster`; } else if (performanceRatio < 0.9) { fasterOperation = operation1.name; recommendation = `${operation1.name} is ${(1 / performanceRatio).toFixed(2)}x faster`; } else { fasterOperation = 'Comparable performance'; recommendation = 'Both approaches have similar performance'; } return { operation1: { name: operation1.name, time: result1.averageTime, result: result1.result, error: result1.error, memoryUsed: result1.memoryUsed, }, operation2: { name: operation2.name, time: result2.averageTime, result: result2.result, error: result2.error, memoryUsed: result2.memoryUsed, }, comparison: { fasterOperation, timeDifference, performanceRatio, recommendation, }, }; } static async runCustomBenchmarkSuite(operations, config = {}) { const suiteName = `Custom Benchmark Suite (${operations.length} operations)`; console.log(`\n๐Ÿš€ Starting ${suiteName}`); console.log('='.repeat(80)); const results = []; let successfulOperations = 0; let failedOperations = 0; for (const [index, operation] of operations.entries()) { console.log(`\n๐Ÿ“Š ${index + 1}/${operations.length}: ${operation.name}`); try { const result = await this.benchmarkCustomOperation(operation, { ...config, showProgress: true, }); results.push(result); if (!result.error) { successfulOperations++; console.log(` โœ… Average: ${result.averageTime.toFixed(2)}ms (${result.iterations} iterations)`); if (result.memoryUsed) { console.log(` ๐Ÿง  Memory: ${(result.memoryUsed / 1024 / 1024).toFixed(2)}MB`); } } else { failedOperations++; console.log(` โŒ Failed: ${result.error}`); } } catch (error) { failedOperations++; const errorMessage = error instanceof Error ? error.message : String(error); console.log(` โŒ Exception: ${errorMessage}`); results.push({ operationName: operation.name, averageTime: 0, totalTime: 0, iterations: 0, result: null, error: errorMessage, }); } } const successfulResults = results.filter((r) => !r.error && r.averageTime > 0); const avgSyncTime = successfulResults.length > 0 ? successfulResults.reduce((sum, r) => sum + r.averageTime, 0) / successfulResults.length : 0; const avgAsyncTime = avgSyncTime; const overallRecommendation = successfulOperations > failedOperations ? `${((successfulOperations / operations.length) * 100).toFixed(1)}% success rate - Good performance` : 'Multiple failures detected - Review operation implementations'; console.log('\n' + '='.repeat(80)); console.log('๐Ÿ“ˆ CUSTOM BENCHMARK SUMMARY'); console.log('='.repeat(80)); console.log(`โœ… Successful operations: ${successfulOperations}/${operations.length}`); console.log(`โŒ Failed operations: ${failedOperations}`); if (successfulResults.length > 0) { console.log(`โฑ๏ธ Average execution time: ${avgSyncTime.toFixed(2)}ms`); console.log(`๐Ÿ† Fastest: ${successfulResults.reduce((min, current) => current.averageTime < min.averageTime ? current : min).operationName}`); console.log(`๐ŸŒ Slowest: ${successfulResults.reduce((max, current) => current.averageTime > max.averageTime ? current : max).operationName}`); } console.log(`๐Ÿ’ก ${overallRecommendation}`); console.log('='.repeat(80)); return { suiteName, results, summary: { totalOperations: operations.length, successfulOperations, failedOperations, avgSyncTime, avgAsyncTime, overallRecommendation, }, }; } } exports.BenchmarkUtils = BenchmarkUtils; //# sourceMappingURL=benchmark.utils.js.map