/** * 🧠 Graph Scale Performance Benchmarks * * Comprehensive performance validation for large-scale graph operations * and O(1) traversal validation. Tests industry-leading performance targets: * * - O(1) neighbor lookup: <1ms for 10M relationships * - Memory efficiency: ~24 bytes per relationship * - Index update: <5ms per relationship amortized * - Rebuild performance from storage * * NO MOCKS, NO STUBS - REAL PRODUCTION CODE AT SCALE */ import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest' import { Brainy } from '../../src/brainy.js' import { GraphAdjacencyIndex } from '../../src/graph/graphAdjacencyIndex.js' import { EntityIdMapper } from '../../src/utils/entityIdMapper.js' import { MemoryStorage } from '../../src/storage/adapters/memoryStorage.js' import { performance } from 'perf_hooks' // Performance targets and constants const PERFORMANCE_TARGETS = { O1_LOOKUP: 1.0, // <1ms for O(1) neighbor lookup INDEX_UPDATE: 5.0, // <5ms amortized per relationship update MEMORY_PER_REL: 24, // ~24 bytes per relationship REBUILD_RATE: 1000, // 1000 relationships/second rebuild rate CONCURRENT_LOAD: 100 // 100 concurrent operations } as const // Test scales for different environments const TEST_SCALES = { CI: { relationships: 10000, nodes: 5000, concurrentOps: 10 }, DEVELOPMENT: { relationships: 100000, nodes: 50000, concurrentOps: 50 }, PRODUCTION: { relationships: 1000000, nodes: 100000, concurrentOps: 100 } } as const // Statistical analysis helpers class PerformanceStats { private samples: number[] = [] addSample(value: number) { this.samples.push(value) } get mean(): number { return this.samples.reduce((a, b) => a + b, 0) / this.samples.length } get median(): number { const sorted = [...this.samples].sort((a, b) => a - b) const mid = Math.floor(sorted.length / 2) return sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid] } get p95(): number { const sorted = [...this.samples].sort((a, b) => a - b) const index = Math.floor(sorted.length * 0.95) return sorted[index] } get p99(): number { const sorted = [...this.samples].sort((a, b) => a - b) const index = Math.floor(sorted.length * 0.99) return sorted[index] } get stdDev(): number { const mean = this.mean const variance = this.samples.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0) / this.samples.length return Math.sqrt(variance) } get min(): number { return Math.min(...this.samples) } get max(): number { return Math.max(...this.samples) } reset() { this.samples = [] } toString(): string { return `mean=${this.mean.toFixed(2)}ms, median=${this.median.toFixed(2)}ms, p95=${this.p95.toFixed(2)}ms, p99=${this.p99.toFixed(2)}ms` } } // Determine test scale based on environment function getTestScale() { if (process.env.CI) return TEST_SCALES.CI if (process.env.NODE_ENV === 'production') return TEST_SCALES.PRODUCTION return TEST_SCALES.DEVELOPMENT } describe('🧠 Graph Scale Performance Benchmarks', () => { let brain: Brainy let graphIndex: GraphAdjacencyIndex let storage: MemoryStorage let idMapper: EntityIdMapper const scale = getTestScale() /** Resolve a UUID to its entity int for the 8.0 BigInt boundary. */ const entityInt = (uuid: string): bigint => BigInt(idMapper.getOrAssign(uuid)) /** Map returned entity ints back to UUIDs. */ const intsToUuids = (ints: bigint[]): string[] => ints .map((i) => idMapper.getUuid(Number(i))) .filter((u): u is string => u !== undefined) // Performance tracking const lookupStats = new PerformanceStats() const updateStats = new PerformanceStats() const memoryStats = new PerformanceStats() beforeAll(async () => { console.log(`\nšŸš€ Initializing Graph Scale Performance Tests`) console.log(`šŸ“Š Scale: ${scale.relationships.toLocaleString()} relationships, ${scale.nodes.toLocaleString()} nodes`) console.log(`šŸŽÆ Targets: O(1) <${PERFORMANCE_TARGETS.O1_LOOKUP}ms, Memory ~${PERFORMANCE_TARGETS.MEMORY_PER_REL} bytes/rel\n`) const startTime = Date.now() // Initialize storage and graph index storage = new MemoryStorage() await storage.init() idMapper = new EntityIdMapper({ storage }) await idMapper.init() graphIndex = new GraphAdjacencyIndex(storage, { maxIndexSize: scale.nodes, autoOptimize: true }, idMapper) // Initialize Brainy for unified testing brain = new Brainy({ requireSubtype: false, storage: { type: 'memory' }, enableGraphIndex: true, enableMetadataIndex: true }) await brain.init() // Generate test data console.log('šŸ“ Generating test graph data...') await generateTestGraph(scale.nodes, scale.relationships) const elapsed = Date.now() - startTime console.log(`āœ… Setup complete in ${(elapsed / 1000).toFixed(1)}s\n`) }, 300000) // 5 minute timeout afterAll(async () => { await brain?.close() await graphIndex?.close() }) beforeEach(() => { // Reset stats for each test lookupStats.reset() updateStats.reset() memoryStats.reset() }) /** * Generate a realistic test graph with the specified scale */ async function generateTestGraph(nodeCount: number, relationshipCount: number) { const batchSize = 1000 // Generate nodes for (let i = 0; i < nodeCount; i += batchSize) { const batch = [] for (let j = 0; j < batchSize && i + j < nodeCount; j++) { const idx = i + j batch.push({ id: `node-${idx}`, data: `Test entity ${idx}`, metadata: { type: idx % 5 === 0 ? 'user' : idx % 3 === 0 ? 'document' : 'concept', category: ['tech', 'science', 'business', 'health', 'education'][idx % 5], created: Date.now() - idx * 1000 } }) } await brain.addMany(batch) } // Generate relationships with realistic patterns const relationshipTypes = ['follows', 'references', 'related', 'contains', 'belongs_to'] let relationshipsAdded = 0 while (relationshipsAdded < relationshipCount) { const batch = [] for (let i = 0; i < Math.min(batchSize, relationshipCount - relationshipsAdded); i++) { const sourceId = `node-${Math.floor(Math.random() * nodeCount)}` const targetId = `node-${Math.floor(Math.random() * nodeCount)}` const type = relationshipTypes[Math.floor(Math.random() * relationshipTypes.length)] if (sourceId !== targetId) { // Avoid self-references batch.push({ from: sourceId, to: targetId, type, metadata: { strength: Math.random(), created: Date.now() - Math.random() * 86400000 // Random time within 24h } }) } } await brain.relateMany(batch) relationshipsAdded += batch.length if (relationshipsAdded % 10000 === 0) { console.log(` Added ${relationshipsAdded.toLocaleString()}/${relationshipCount.toLocaleString()} relationships...`) } } } describe('1. GraphAdjacencyIndex Performance Benchmarks', () => { it('should achieve O(1) neighbor lookup validation (<1ms for large graphs)', async () => { console.log(`\nšŸ” Testing O(1) neighbor lookups on ${scale.relationships.toLocaleString()} relationships...`) // Warm up the index await graphIndex.rebuild() await graphIndex.getNeighbors(entityInt('node-100')) // Warm up // Test random lookups const testIterations = Math.min(1000, scale.nodes / 10) const sampleNodes = Array.from({ length: testIterations }, () => `node-${Math.floor(Math.random() * scale.nodes)}` ) for (const nodeId of sampleNodes) { const startTime = performance.now() const neighbors = await graphIndex.getNeighbors(entityInt(nodeId)) const elapsed = performance.now() - startTime lookupStats.addSample(elapsed) // Each lookup should be sub-millisecond expect(elapsed).toBeLessThan(PERFORMANCE_TARGETS.O1_LOOKUP) expect(Array.isArray(neighbors)).toBe(true) } console.log(`āœ… O(1) Lookup Performance: ${lookupStats.toString()}`) console.log(` Target: <${PERFORMANCE_TARGETS.O1_LOOKUP}ms per lookup`) console.log(` Best: ${lookupStats.min.toFixed(3)}ms, Worst: ${lookupStats.max.toFixed(3)}ms`) // Statistical validation expect(lookupStats.p95).toBeLessThan(PERFORMANCE_TARGETS.O1_LOOKUP) expect(lookupStats.p99).toBeLessThan(PERFORMANCE_TARGETS.O1_LOOKUP * 2) // Allow some variance for p99 }) it('should validate memory usage (~24 bytes per relationship)', async () => { const stats = graphIndex.getStats() console.log(`\nšŸ’¾ Memory Usage Analysis:`) console.log(` Total relationships: ${stats.totalRelationships.toLocaleString()}`) console.log(` Source nodes: ${stats.sourceNodes.toLocaleString()}`) console.log(` Target nodes: ${stats.targetNodes.toLocaleString()}`) console.log(` Memory usage: ${(stats.memoryUsage / 1024 / 1024).toFixed(2)} MB`) const bytesPerRelationship = stats.memoryUsage / stats.totalRelationships console.log(` Bytes per relationship: ${bytesPerRelationship.toFixed(1)}`) // Validate memory efficiency expect(bytesPerRelationship).toBeLessThan(PERFORMANCE_TARGETS.MEMORY_PER_REL * 1.5) // Allow 50% margin expect(bytesPerRelationship).toBeGreaterThan(PERFORMANCE_TARGETS.MEMORY_PER_REL * 0.5) // Don't be too efficient (might indicate missing data) // Memory should scale linearly with relationships expect(stats.memoryUsage).toBeGreaterThan(0) }) it('should validate index update performance (<5ms per relationship amortized)', async () => { console.log(`\n⚔ Testing index update performance...`) // Test batch updates const batchSize = 100 const testBatches = Math.min(10, Math.floor(scale.nodes / batchSize)) for (let batch = 0; batch < testBatches; batch++) { const startTime = performance.now() // Add relationships in batch const relationships = [] for (let i = 0; i < batchSize; i++) { const sourceId = `node-${Math.floor(Math.random() * scale.nodes)}` const targetId = `node-${Math.floor(Math.random() * scale.nodes)}` relationships.push({ from: sourceId, to: targetId, type: 'test_relationship', metadata: { batch, index: i } }) } await brain.relateMany(relationships) const elapsed = performance.now() - startTime const amortizedTime = elapsed / batchSize updateStats.addSample(amortizedTime) // Each update should be fast expect(amortizedTime).toBeLessThan(PERFORMANCE_TARGETS.INDEX_UPDATE) } console.log(`āœ… Index Update Performance: ${updateStats.toString()}`) console.log(` Target: <${PERFORMANCE_TARGETS.INDEX_UPDATE}ms amortized per relationship`) // Statistical validation expect(updateStats.p95).toBeLessThan(PERFORMANCE_TARGETS.INDEX_UPDATE * 1.5) }) it('should validate rebuild performance from storage', async () => { console.log(`\nšŸ”„ Testing index rebuild performance...`) const startTime = performance.now() await graphIndex.rebuild() const rebuildTime = performance.now() - startTime const rebuildRate = scale.relationships / (rebuildTime / 1000) // relationships per second console.log(`āœ… Rebuild Performance:`) console.log(` Total time: ${(rebuildTime / 1000).toFixed(2)}s`) console.log(` Rate: ${rebuildRate.toFixed(0)} relationships/second`) console.log(` Target: >${PERFORMANCE_TARGETS.REBUILD_RATE} relationships/second`) // Validate rebuild performance expect(rebuildRate).toBeGreaterThan(PERFORMANCE_TARGETS.REBUILD_RATE) // Rebuild should complete within reasonable time const expectedMaxTime = scale.relationships / PERFORMANCE_TARGETS.REBUILD_RATE * 1000 expect(rebuildTime).toBeLessThan(expectedMaxTime * 2) // Allow 2x margin // Verify index integrity after rebuild const stats = graphIndex.getStats() expect(stats.totalRelationships).toBeGreaterThan(0) expect(stats.sourceNodes).toBeGreaterThan(0) expect(stats.targetNodes).toBeGreaterThan(0) }) }) describe('2. Large-Scale Graph Operations', () => { it('should handle 100K+ relationship graph construction', async () => { console.log(`\nšŸ—ļø Testing large-scale graph construction...`) const constructionStart = performance.now() // Add additional relationships to reach target scale const additionalRelationships = Math.max(0, 100000 - scale.relationships) if (additionalRelationships > 0) { const batchSize = 1000 let added = 0 while (added < additionalRelationships) { const batch = [] for (let i = 0; i < Math.min(batchSize, additionalRelationships - added); i++) { batch.push({ from: `node-${Math.floor(Math.random() * scale.nodes)}`, to: `node-${Math.floor(Math.random() * scale.nodes)}`, type: 'bulk_relationship', metadata: { batchId: Math.floor(added / batchSize) } }) } await brain.relateMany(batch) added += batch.length } } const constructionTime = performance.now() - constructionStart console.log(`āœ… Large-scale construction:`) console.log(` Time: ${(constructionTime / 1000).toFixed(2)}s`) console.log(` Rate: ${(scale.relationships / (constructionTime / 1000)).toFixed(0)} relationships/s`) // Construction should be efficient expect(constructionTime).toBeLessThan(300000) // Less than 5 minutes }) it('should handle million-node graph traversal', async () => { console.log(`\n🚶 Testing large graph traversal...`) // Test traversal from multiple starting points const startNodes = ['node-0', 'node-100', 'node-1000', 'node-10000'] const traversalStats = new PerformanceStats() for (const startNode of startNodes) { const startTime = performance.now() // Perform BFS traversal with depth limit const visited = new Set() const queue: Array<{ id: string; depth: number }> = [{ id: startNode, depth: 0 }] let nodesTraversed = 0 const maxDepth = 3 const maxNodes = 1000 while (queue.length > 0 && nodesTraversed < maxNodes) { const { id, depth } = queue.shift()! if (visited.has(id) || depth > maxDepth) continue visited.add(id) nodesTraversed++ // Get neighbors (BigInt boundary: ints out, mapped back to UUIDs) const neighborInts = await graphIndex.getNeighbors(entityInt(id), { direction: 'out' }) for (const neighbor of intsToUuids(neighborInts)) { if (!visited.has(neighbor)) { queue.push({ id: neighbor, depth: depth + 1 }) } } } const traversalTime = performance.now() - startTime traversalStats.addSample(traversalTime) console.log(` ${startNode}: ${nodesTraversed} nodes in ${(traversalTime).toFixed(2)}ms`) } console.log(`āœ… Graph traversal performance: ${traversalStats.toString()}`) // Traversal should be fast expect(traversalStats.p95).toBeLessThan(100) // <100ms for traversal }) it('should handle complex graph query patterns', async () => { console.log(`\nšŸ” Testing complex graph query patterns...`) const queryPatterns = [ { name: 'Single node neighbors', query: { connected: { from: 'node-100' } } }, { name: 'Bidirectional connections', query: { connected: { from: 'node-200', direction: 'both' } } }, { name: 'Multi-hop paths', query: { connected: { from: 'node-300', depth: 2 } } }, { name: 'Filtered connections', query: { connected: { from: 'node-400' }, where: { type: 'follows' } } } ] const patternStats = new PerformanceStats() for (const pattern of queryPatterns) { const startTime = performance.now() const results = await brain.find(pattern.query) const elapsed = performance.now() - startTime patternStats.addSample(elapsed) console.log(` ${pattern.name}: ${results.length} results in ${elapsed.toFixed(2)}ms`) // Complex queries should still be fast expect(elapsed).toBeLessThan(500) // <500ms for complex queries expect(Array.isArray(results)).toBe(true) } console.log(`āœ… Complex query performance: ${patternStats.toString()}`) }) it('should validate memory efficiency under scale', async () => { console.log(`\nšŸ“Š Memory efficiency analysis under scale...`) const initialMemory = process.memoryUsage() const initialHeapUsed = initialMemory.heapUsed // Perform memory-intensive operations const operations = [] for (let i = 0; i < 100; i++) { operations.push( brain.find({ connected: { from: `node-${Math.floor(Math.random() * scale.nodes)}`, depth: 2 } }) ) } await Promise.all(operations) const finalMemory = process.memoryUsage() const finalHeapUsed = finalMemory.heapUsed const memoryDelta = finalHeapUsed - initialHeapUsed console.log(`āœ… Memory efficiency:`) console.log(` Initial heap: ${(initialHeapUsed / 1024 / 1024).toFixed(2)} MB`) console.log(` Final heap: ${(finalHeapUsed / 1024 / 1024).toFixed(2)} MB`) console.log(` Delta: ${(memoryDelta / 1024 / 1024).toFixed(2)} MB`) // Memory usage should be reasonable expect(memoryDelta).toBeLessThan(100 * 1024 * 1024) // Less than 100MB increase // Force garbage collection if available if (global.gc) { global.gc() const afterGc = process.memoryUsage() console.log(` After GC: ${(afterGc.heapUsed / 1024 / 1024).toFixed(2)} MB`) } }) }) describe('3. Unified find() Performance', () => { it('should handle vector+graph+fields combined queries at scale', async () => { console.log(`\nšŸ”— Testing unified find() with combined queries...`) const combinedQueries = [ { name: 'Vector + Graph', query: { similar: 'technology artificial intelligence', connected: { from: 'node-1000', depth: 1 }, limit: 20 } }, { name: 'Vector + Fields', query: { similar: 'machine learning', where: { category: 'tech', type: 'document' }, limit: 20 } }, { name: 'Graph + Fields', query: { connected: { from: 'node-2000', depth: 2 }, where: { created: { $gt: Date.now() - 86400000 } }, // Last 24h limit: 20 } }, { name: 'Triple Intelligence', query: { similar: 'neural networks', connected: { from: 'node-3000' }, where: { category: 'science' }, limit: 20 } } ] const unifiedStats = new PerformanceStats() for (const testCase of combinedQueries) { const startTime = performance.now() const results = await brain.find(testCase.query) const elapsed = performance.now() - startTime unifiedStats.addSample(elapsed) console.log(` ${testCase.name}: ${results.length} results in ${elapsed.toFixed(2)}ms`) // Unified queries should be efficient expect(elapsed).toBeLessThan(1000) // <1s for combined queries expect(results.length).toBeGreaterThan(0) expect(results[0].score).toBeDefined() } console.log(`āœ… Unified query performance: ${unifiedStats.toString()}`) }) it('should validate parallel execution performance', async () => { console.log(`\n⚔ Testing parallel query execution...`) const parallelQueries = Array.from({ length: 10 }, (_, i) => ({ similar: `query ${i}`, connected: { from: `node-${i * 1000}`, depth: 1 }, where: { category: ['tech', 'science', 'business'][i % 3] }, limit: 10 })) const parallelStart = performance.now() const results = await Promise.all(parallelQueries.map(query => brain.find(query))) const parallelTime = performance.now() - parallelStart const sequentialStart = performance.now() for (const query of parallelQueries) { await brain.find(query) } const sequentialTime = performance.now() - sequentialStart const speedup = sequentialTime / parallelTime console.log(`āœ… Parallel execution:`) console.log(` Parallel time: ${parallelTime.toFixed(2)}ms`) console.log(` Sequential time: ${sequentialTime.toFixed(2)}ms`) console.log(` Speedup: ${speedup.toFixed(2)}x`) // Parallel execution should provide speedup expect(speedup).toBeGreaterThan(1.5) // At least 1.5x speedup expect(results.length).toBe(10) results.forEach(resultSet => { expect(Array.isArray(resultSet)).toBe(true) expect(resultSet.length).toBeGreaterThan(0) }) }) it('should validate query optimization effectiveness', async () => { console.log(`\nšŸŽÆ Testing query optimization effectiveness...`) // Test different query patterns to see optimization effectiveness const optimizationTests = [ { name: 'ID lookup (fast path)', query: { id: 'node-100' }, expectedTime: 1 }, { name: 'Multiple IDs (fast path)', query: { ids: ['node-100', 'node-200', 'node-300'] }, expectedTime: 5 }, { name: 'Vector search only', query: { similar: 'test query', limit: 10 }, expectedTime: 50 }, { name: 'Metadata filter only', query: { where: { category: 'tech' }, limit: 10 }, expectedTime: 20 }, { name: 'Graph traversal only', query: { connected: { from: 'node-1000' }, limit: 10 }, expectedTime: 30 } ] const optimizationStats = new PerformanceStats() for (const test of optimizationTests) { const startTime = performance.now() const results = await brain.find(test.query) const elapsed = performance.now() - startTime optimizationStats.addSample(elapsed) console.log(` ${test.name}: ${elapsed.toFixed(2)}ms (target: <${test.expectedTime}ms)`) // Each query should meet its performance target expect(elapsed).toBeLessThan(test.expectedTime * 2) // Allow 2x margin expect(Array.isArray(results)).toBe(true) } console.log(`āœ… Query optimization: ${optimizationStats.toString()}`) }) it('should validate memory usage during large queries', async () => { console.log(`\nšŸ’¾ Memory usage during large queries...`) const initialMemory = process.memoryUsage() // Execute large queries const largeQueries = [ brain.find({ similar: 'comprehensive test', limit: 100 }), brain.find({ where: { category: 'tech' }, limit: 100 }), brain.find({ connected: { from: 'node-1000', depth: 3 }, limit: 100 }), brain.find({ similar: 'large scale', connected: { from: 'node-2000', depth: 2 }, where: { type: 'document' }, limit: 100 }) ] await Promise.all(largeQueries) const finalMemory = process.memoryUsage() const memoryIncrease = finalMemory.heapUsed - initialMemory.heapUsed console.log(`āœ… Large query memory usage:`) console.log(` Memory increase: ${(memoryIncrease / 1024 / 1024).toFixed(2)} MB`) console.log(` Peak RSS: ${(finalMemory.rss / 1024 / 1024).toFixed(2)} MB`) // Memory usage should be reasonable for large queries expect(memoryIncrease).toBeLessThan(50 * 1024 * 1024) // Less than 50MB increase }) }) describe('4. Concurrent Load Testing', () => { it('should handle multiple concurrent graph operations', async () => { console.log(`\nšŸ”„ Testing concurrent graph operations...`) const concurrentOps = Math.min(scale.concurrentOps, PERFORMANCE_TARGETS.CONCURRENT_LOAD) const operations: Promise[] = [] // Mix of different operation types for (let i = 0; i < concurrentOps; i++) { const operationType = i % 4 switch (operationType) { case 0: // Neighbor lookup operations.push(graphIndex.getNeighbors(entityInt(`node-${Math.floor(Math.random() * scale.nodes)}`))) break case 1: // Unified find operations.push(brain.find({ connected: { from: `node-${Math.floor(Math.random() * scale.nodes)}` }, limit: 5 })) break case 2: // Relationship addition operations.push(brain.relate({ from: `node-${Math.floor(Math.random() * scale.nodes)}`, to: `node-${Math.floor(Math.random() * scale.nodes)}`, type: 'concurrent_test' })) break case 3: // Complex query operations.push(brain.find({ similar: `concurrent query ${i}`, where: { category: ['tech', 'science'][i % 2] }, limit: 3 })) break } } const concurrentStart = performance.now() const results = await Promise.all(operations) const concurrentTime = performance.now() - concurrentStart console.log(`āœ… Concurrent operations:`) console.log(` ${concurrentOps} operations completed in ${concurrentTime.toFixed(2)}ms`) console.log(` Average time per operation: ${(concurrentTime / concurrentOps).toFixed(2)}ms`) // Concurrent operations should complete efficiently expect(concurrentTime).toBeLessThan(5000) // Less than 5 seconds for all operations expect(results.length).toBe(concurrentOps) }) it('should handle spike testing for sudden traffic increases', async () => { console.log(`\nšŸ“ˆ Testing traffic spike handling...`) const spikeLevels = [10, 50, 100, 200] const spikeResults: number[] = [] for (const spikeLevel of spikeLevels) { const spikeOperations = Array.from({ length: spikeLevel }, () => brain.find({ connected: { from: `node-${Math.floor(Math.random() * scale.nodes)}` } }) ) const spikeStart = performance.now() await Promise.all(spikeOperations) const spikeTime = performance.now() - spikeStart spikeResults.push(spikeTime) console.log(` Spike ${spikeLevel}: ${spikeTime.toFixed(2)}ms (${(spikeTime / spikeLevel).toFixed(2)}ms/op)`) // Even under spike, performance should be reasonable expect(spikeTime).toBeLessThan(spikeLevel * 50) // <50ms per operation on average } // Performance should degrade gracefully under load const degradation = spikeResults[spikeResults.length - 1] / spikeResults[0] console.log(` Performance degradation: ${degradation.toFixed(2)}x under 20x load increase`) // Allow some degradation but not exponential expect(degradation).toBeLessThan(10) // Less than 10x slower under 20x load }) it('should detect memory leaks under sustained load', async () => { console.log(`\nšŸ•µļø Testing memory leak detection...`) const leakTestDuration = 30000 // 30 seconds const leakTestStart = Date.now() const memorySamples: number[] = [] // Run continuous operations for leak detection while (Date.now() - leakTestStart < leakTestDuration) { const operations = Array.from({ length: 10 }, () => brain.find({ connected: { from: `node-${Math.floor(Math.random() * scale.nodes)}` } }) ) await Promise.all(operations) // Sample memory usage const memUsage = process.memoryUsage() memorySamples.push(memUsage.heapUsed) // Small delay to prevent overwhelming the system await new Promise(resolve => setTimeout(resolve, 100)) } const initialMemory = memorySamples[0] const finalMemory = memorySamples[memorySamples.length - 1] const memoryGrowth = finalMemory - initialMemory const growthRate = memoryGrowth / leakTestDuration * 1000 // bytes per second console.log(`āœ… Memory leak analysis:`) console.log(` Initial memory: ${(initialMemory / 1024 / 1024).toFixed(2)} MB`) console.log(` Final memory: ${(finalMemory / 1024 / 1024).toFixed(2)} MB`) console.log(` Growth: ${(memoryGrowth / 1024 / 1024).toFixed(2)} MB`) console.log(` Growth rate: ${(growthRate / 1024).toFixed(2)} KB/s`) // Memory growth should be minimal (less than 10MB over 30 seconds) expect(memoryGrowth).toBeLessThan(10 * 1024 * 1024) // Growth rate should be very low expect(growthRate).toBeLessThan(100 * 1024) // Less than 100KB/s growth }) it('should validate resource exhaustion handling', async () => { console.log(`\n🚨 Testing resource exhaustion handling...`) const exhaustionTests = [ { name: 'Deep recursion', operation: () => brain.find({ connected: { from: 'node-0', depth: 10 } }) }, { name: 'Large result sets', operation: () => brain.find({ connected: { from: 'node-1000', depth: 5 }, limit: 10000 }) }, { name: 'Complex filters', operation: () => brain.find({ where: { $and: [ { category: 'tech' }, { type: 'document' }, { created: { $gt: Date.now() - 86400000 } }, { score: { $gt: 0.5 } } ] }, limit: 1000 }) } ] for (const test of exhaustionTests) { const startTime = performance.now() try { const result = await test.operation() const elapsed = performance.now() - startTime console.log(` ${test.name}: ${elapsed.toFixed(2)}ms (${Array.isArray(result) ? result.length : 'N/A'} results)`) // Operations should complete without throwing expect(elapsed).toBeLessThan(10000) // Less than 10 seconds } catch (error) { console.log(` ${test.name}: Failed with ${error.message}`) // Some operations might legitimately fail under extreme conditions expect(error.message).toMatch(/timeout|limit|memory|recursion/i) } } console.log(`āœ… Resource exhaustion handling validated`) }) }) describe('5. Real-World Scenarios', () => { it('should handle social network analysis (friends, followers, connections)', async () => { console.log(`\nšŸ‘„ Testing social network analysis...`) // Create a social network scenario const socialUsers = Array.from({ length: 1000 }, (_, i) => `user-${i}`) const socialRelationships = [] // Create follower relationships (scale-free network) for (let i = 0; i < socialUsers.length; i++) { const followerCount = Math.floor(Math.random() * 50) + 1 // 1-50 followers for (let j = 0; j < followerCount; j++) { const targetUser = socialUsers[Math.floor(Math.random() * socialUsers.length)] if (targetUser !== socialUsers[i]) { socialRelationships.push({ from: socialUsers[i], to: targetUser, type: 'follows', metadata: { strength: Math.random() } }) } } } await brain.relateMany(socialRelationships) // Test social network queries const socialQueries = [ { name: 'Find influencers', query: { connected: { from: 'user-0', direction: 'in' }, limit: 20 } }, { name: 'Find following', query: { connected: { from: 'user-100', direction: 'out' }, limit: 20 } }, { name: 'Mutual connections', query: { connected: { from: 'user-200', direction: 'both' }, where: { type: 'follows' }, limit: 20 } } ] const socialStats = new PerformanceStats() for (const socialQuery of socialQueries) { const startTime = performance.now() const results = await brain.find(socialQuery.query) const elapsed = performance.now() - startTime socialStats.addSample(elapsed) console.log(` ${socialQuery.name}: ${results.length} connections in ${elapsed.toFixed(2)}ms`) } console.log(`āœ… Social network performance: ${socialStats.toString()}`) expect(socialStats.p95).toBeLessThan(100) }) it('should handle knowledge graph traversal (entity relationships)', async () => { console.log(`\n🧠 Testing knowledge graph traversal...`) // Create knowledge graph entities const entities = [ 'Machine Learning', 'Neural Networks', 'Deep Learning', 'AI', 'Computer Vision', 'Natural Language Processing', 'Supervised Learning', 'Unsupervised Learning', 'Reinforcement Learning', 'Data Science', 'Statistics', 'Python', 'TensorFlow' ] // Create semantic relationships const knowledgeRelationships = [ { from: 'Machine Learning', to: 'AI', type: 'subfield_of' }, { from: 'Deep Learning', to: 'Machine Learning', type: 'subfield_of' }, { from: 'Neural Networks', to: 'Deep Learning', type: 'foundation_of' }, { from: 'Computer Vision', to: 'AI', type: 'application_of' }, { from: 'Natural Language Processing', to: 'AI', type: 'application_of' }, { from: 'Supervised Learning', to: 'Machine Learning', type: 'type_of' }, { from: 'Unsupervised Learning', to: 'Machine Learning', type: 'type_of' }, { from: 'Reinforcement Learning', to: 'Machine Learning', type: 'type_of' }, { from: 'Data Science', to: 'Machine Learning', type: 'uses' }, { from: 'Statistics', to: 'Data Science', type: 'foundation_of' }, { from: 'Python', to: 'Machine Learning', type: 'tool_for' }, { from: 'TensorFlow', to: 'Machine Learning', type: 'tool_for' } ] // Add entities and relationships for (const entity of entities) { await brain.add({ id: entity, data: `Knowledge about ${entity}`, metadata: { type: 'concept', domain: 'AI' } }) } await brain.relateMany(knowledgeRelationships) // Test knowledge graph queries const knowledgeQueries = [ { name: 'Find related concepts', query: { connected: { from: 'Machine Learning', depth: 2 }, limit: 15 } }, { name: 'Find applications', query: { connected: { from: 'AI', direction: 'in' }, where: { type: 'application_of' }, limit: 10 } }, { name: 'Semantic path finding', query: { similar: 'artificial intelligence applications', connected: { from: 'AI', depth: 3 }, limit: 20 } } ] const knowledgeStats = new PerformanceStats() for (const kgQuery of knowledgeQueries) { const startTime = performance.now() const results = await brain.find(kgQuery.query) const elapsed = performance.now() - startTime knowledgeStats.addSample(elapsed) console.log(` ${kgQuery.name}: ${results.length} concepts in ${elapsed.toFixed(2)}ms`) } console.log(`āœ… Knowledge graph performance: ${knowledgeStats.toString()}`) expect(knowledgeStats.p95).toBeLessThan(200) }) it('should handle recommendation system queries', async () => { console.log(`\nšŸŽÆ Testing recommendation system queries...`) // Create recommendation scenario with users, items, and ratings const users = Array.from({ length: 500 }, (_, i) => `user-${i}`) const items = Array.from({ length: 200 }, (_, i) => `item-${i}`) const categories = ['electronics', 'books', 'clothing', 'movies', 'music'] // Add users and items for (const user of users) { await brain.add({ id: user, data: `User profile for ${user}`, metadata: { type: 'user', category: 'consumer' } }) } for (const item of items) { const category = categories[Math.floor(Math.random() * categories.length)] await brain.add({ id: item, data: `Product: ${item}`, metadata: { type: 'product', category, price: Math.random() * 100 } }) } // Create purchase/rating relationships const purchaseRelationships = [] for (let i = 0; i < 2000; i++) { const user = users[Math.floor(Math.random() * users.length)] const item = items[Math.floor(Math.random() * items.length)] const rating = Math.floor(Math.random() * 5) + 1 purchaseRelationships.push({ from: user, to: item, type: 'purchased', metadata: { rating, timestamp: Date.now() - Math.random() * 2592000000 } // Random within 30 days }) } await brain.relateMany(purchaseRelationships) // Test recommendation queries const recommendationQueries = [ { name: 'User purchase history', query: { connected: { from: 'user-100', direction: 'out' }, limit: 10 } }, { name: 'Item popularity', query: { connected: { from: 'item-50', direction: 'in' }, limit: 15 } }, { name: 'Similar user recommendations', query: { connected: { from: 'user-200', direction: 'out' }, where: { rating: { $gte: 4 } }, limit: 10 } }, { name: 'Category-based recommendations', query: { similar: 'electronics gadgets', connected: { from: 'user-300', depth: 2 }, where: { category: 'electronics' }, limit: 15 } } ] const recommendationStats = new PerformanceStats() for (const recQuery of recommendationQueries) { const startTime = performance.now() const results = await brain.find(recQuery.query) const elapsed = performance.now() - startTime recommendationStats.addSample(elapsed) console.log(` ${recQuery.name}: ${results.length} recommendations in ${elapsed.toFixed(2)}ms`) } console.log(`āœ… Recommendation system performance: ${recommendationStats.toString()}`) expect(recommendationStats.p95).toBeLessThan(150) }) it('should handle path finding and network analysis', async () => { console.log(`\nšŸ›£ļø Testing path finding and network analysis...`) // Create a network topology for path finding const networkNodes = Array.from({ length: 100 }, (_, i) => `network-${i}`) const networkConnections = [] // Create a mesh network with some clustering for (let i = 0; i < networkNodes.length; i++) { const connections = Math.floor(Math.random() * 5) + 2 // 2-6 connections per node for (let j = 0; j < connections; j++) { let targetIndex = i + Math.floor(Math.random() * 10) - 5 // Nearby nodes if (targetIndex < 0) targetIndex = 0 if (targetIndex >= networkNodes.length) targetIndex = networkNodes.length - 1 const targetNode = networkNodes[targetIndex] if (targetNode !== networkNodes[i]) { networkConnections.push({ from: networkNodes[i], to: targetNode, type: 'connected_to', metadata: { latency: Math.random() * 100 + 1, // 1-100ms latency bandwidth: Math.random() * 1000 + 100 // 100-1100 Mbps } }) } } } // Add network nodes and connections for (const node of networkNodes) { await brain.add({ id: node, data: `Network node ${node}`, metadata: { type: 'network_node', capacity: Math.random() * 1000 } }) } await brain.relateMany(networkConnections) // Test network analysis queries const networkQueries = [ { name: 'Shortest path analysis', query: { connected: { from: 'network-0', depth: 4 }, limit: 20 } }, { name: 'Network centrality', query: { connected: { from: 'network-50', direction: 'both' }, limit: 25 } }, { name: 'Bottleneck detection', query: { connected: { from: 'network-25', depth: 3 }, where: { capacity: { $lt: 500 } }, limit: 15 } }, { name: 'Network health analysis', query: { similar: 'network connectivity', connected: { from: 'network-75', depth: 2 }, where: { latency: { $lt: 50 } }, limit: 20 } } ] const networkStats = new PerformanceStats() for (const netQuery of networkQueries) { const startTime = performance.now() const results = await brain.find(netQuery.query) const elapsed = performance.now() - startTime networkStats.addSample(elapsed) console.log(` ${netQuery.name}: ${results.length} paths in ${elapsed.toFixed(2)}ms`) } console.log(`āœ… Network analysis performance: ${networkStats.toString()}`) expect(networkStats.p95).toBeLessThan(120) }) }) describe('Performance Summary & Validation', () => { it('should provide comprehensive performance report', async () => { console.log(`\nšŸ“Š ===== COMPREHENSIVE PERFORMANCE REPORT =====`) const finalStats = graphIndex.getStats() const memoryUsage = process.memoryUsage() console.log(`\nšŸŽÆ PERFORMANCE TARGETS VALIDATION:`) console.log(`āœ… O(1) Lookup: ${lookupStats.p95.toFixed(3)}ms < ${PERFORMANCE_TARGETS.O1_LOOKUP}ms target`) console.log(`āœ… Memory/Rel: ${(finalStats.memoryUsage / finalStats.totalRelationships).toFixed(1)} bytes < ${PERFORMANCE_TARGETS.MEMORY_PER_REL} target`) console.log(`āœ… Update: ${updateStats.p95.toFixed(2)}ms < ${PERFORMANCE_TARGETS.INDEX_UPDATE}ms target`) console.log(`āœ… Rebuild: ${(finalStats.totalRelationships / (finalStats.rebuildTime / 1000)).toFixed(0)} rel/s > ${PERFORMANCE_TARGETS.REBUILD_RATE} target`) console.log(`\nšŸ“ˆ SCALE METRICS:`) console.log(` Relationships: ${finalStats.totalRelationships.toLocaleString()}`) console.log(` Source Nodes: ${finalStats.sourceNodes.toLocaleString()}`) console.log(` Target Nodes: ${finalStats.targetNodes.toLocaleString()}`) console.log(` Memory Usage: ${(finalStats.memoryUsage / 1024 / 1024).toFixed(2)} MB`) console.log(` Heap Usage: ${(memoryUsage.heapUsed / 1024 / 1024).toFixed(2)} MB`) console.log(`\n⚔ PERFORMANCE STATISTICS:`) console.log(` Lookup Performance: ${lookupStats.toString()}`) console.log(` Update Performance: ${updateStats.toString()}`) console.log(` Memory Efficiency: ${memoryStats.toString()}`) console.log(`\nšŸ† VALIDATION RESULTS:`) // Validate all performance targets const validations = [ { name: 'O(1) Neighbor Lookup', value: lookupStats.p95, target: PERFORMANCE_TARGETS.O1_LOOKUP, condition: '<' }, { name: 'Memory per Relationship', value: finalStats.memoryUsage / finalStats.totalRelationships, target: PERFORMANCE_TARGETS.MEMORY_PER_REL, condition: '<' }, { name: 'Index Update Performance', value: updateStats.p95, target: PERFORMANCE_TARGETS.INDEX_UPDATE, condition: '<' }, { name: 'Rebuild Rate', value: finalStats.totalRelationships / (finalStats.rebuildTime / 1000), target: PERFORMANCE_TARGETS.REBUILD_RATE, condition: '>' } ] let allPassed = true for (const validation of validations) { const passed = validation.condition === '<' ? validation.value < validation.target : validation.value > validation.target const status = passed ? 'āœ… PASS' : 'āŒ FAIL' console.log(` ${status} ${validation.name}: ${validation.value.toFixed(2)} ${validation.condition} ${validation.target}`) if (!passed) allPassed = false } console.log(`\nšŸŽ‰ OVERALL RESULT: ${allPassed ? 'ALL TARGETS MET' : 'SOME TARGETS MISSED'}`) console.log(`====================================================\n`) // Final validation expect(allPassed).toBe(true) }) }) })