| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 |
- /**
- * Performance Test for Signing Operations
- *
- * Validates that signing operations meet the <50ms performance requirement
- * across all platforms and under various load conditions.
- */
- import { CredentialManager } from '@/core/credential-manager/CredentialManager'
- import { UnifiedSigner } from '@/core/credential-manager/UnifiedSigner'
- import { Platform } from '@/types/credential'
- describe('Signing Performance Test', () => {
- let credentialManager: CredentialManager
- let unifiedSigner: UnifiedSigner
- beforeEach(async () => {
- const config = {
- accounts: [
- {
- id: 'perf-pacifica',
- name: 'Performance Test Pacifica',
- platform: Platform.PACIFICA,
- enabled: true,
- credentials: {
- type: 'ed25519' as const,
- privateKey: 'f26670e2ca334117f8859f9f32e50251641953a30b54f6ffcf82db836cfdfea5'
- }
- },
- {
- id: 'perf-aster',
- name: 'Performance Test Aster',
- platform: Platform.ASTER,
- enabled: true,
- credentials: {
- type: 'secp256k1' as const,
- privateKey: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
- }
- },
- {
- id: 'perf-binance',
- name: 'Performance Test Binance',
- platform: Platform.BINANCE,
- enabled: true,
- credentials: {
- type: 'hmac' as const,
- apiKey: 'test-api-key',
- secretKey: 'test-secret-key'
- }
- }
- ]
- }
- credentialManager = new CredentialManager()
- unifiedSigner = new UnifiedSigner()
- await credentialManager.loadConfiguration(config)
- unifiedSigner.setAccountGetter(async (accountId: string) => {
- return credentialManager.getAccount(accountId)
- })
- })
- afterEach(async () => {
- await credentialManager.shutdown()
- })
- describe('Single Operation Performance', () => {
- test('Pacifica signing should complete within 50ms', async () => {
- const message = new TextEncoder().encode('performance test message')
- const startTime = performance.now()
- const result = await credentialManager.sign('perf-pacifica', message)
- const duration = performance.now() - startTime
- expect(result.success).toBe(true)
- expect(duration).toBeLessThan(50)
- expect(result.metadata?.duration).toBeLessThan(50)
- })
- test('Aster signing should complete within 50ms', async () => {
- const message = new TextEncoder().encode('performance test message')
- const startTime = performance.now()
- const result = await credentialManager.sign('perf-aster', message)
- const duration = performance.now() - startTime
- expect(result.success).toBe(true)
- expect(duration).toBeLessThan(50)
- expect(result.metadata?.duration).toBeLessThan(50)
- })
- test('Binance signing should complete within 50ms', async () => {
- const message = new TextEncoder().encode('performance test message')
- const startTime = performance.now()
- const result = await credentialManager.sign('perf-binance', message)
- const duration = performance.now() - startTime
- expect(result.success).toBe(true)
- expect(duration).toBeLessThan(50)
- expect(result.metadata?.duration).toBeLessThan(50)
- })
- test('UnifiedSigner should meet performance requirements', async () => {
- const message = new TextEncoder().encode('unified signer test')
- const platforms = [
- { accountId: 'perf-pacifica', platform: Platform.PACIFICA },
- { accountId: 'perf-aster', platform: Platform.ASTER },
- { accountId: 'perf-binance', platform: Platform.BINANCE }
- ]
- for (const { accountId, platform } of platforms) {
- const startTime = performance.now()
- const result = await unifiedSigner.sign(accountId, message, {
- forcePlatform: platform,
- collectMetrics: true
- })
- const duration = performance.now() - startTime
- expect(result.success).toBe(true)
- expect(duration).toBeLessThan(50)
- expect(result.metadata?.duration).toBeLessThan(50)
- }
- })
- })
- describe('Batch Operation Performance', () => {
- test('should handle 10 concurrent signing operations within performance limits', async () => {
- const message = new TextEncoder().encode('concurrent test message')
- const operations = Array.from({ length: 10 }, (_, i) => ({
- accountId: ['perf-pacifica', 'perf-aster', 'perf-binance'][i % 3],
- message
- }))
- const startTime = performance.now()
- const results = await Promise.all(
- operations.map(op => credentialManager.sign(op.accountId, op.message))
- )
- const totalDuration = performance.now() - startTime
- expect(results).toHaveLength(10)
- expect(results.every(r => r.success)).toBe(true)
- // Total time for 10 concurrent operations should be reasonable
- expect(totalDuration).toBeLessThan(200)
- // Average time per operation
- const averageTime = totalDuration / 10
- expect(averageTime).toBeLessThan(20)
- // Each individual operation should meet requirement
- results.forEach(result => {
- expect(result.metadata?.duration).toBeLessThan(50)
- })
- })
- test('should handle batch signing with UnifiedSigner', async () => {
- const message = new TextEncoder().encode('batch test message')
- const batchRequests = [
- { accountId: 'perf-pacifica', message },
- { accountId: 'perf-aster', message },
- { accountId: 'perf-binance', message },
- { accountId: 'perf-pacifica', message },
- { accountId: 'perf-aster', message }
- ]
- const startTime = performance.now()
- const results = await unifiedSigner.signBatch(batchRequests)
- const totalDuration = performance.now() - startTime
- expect(results).toHaveLength(5)
- expect(results.every(r => r.success)).toBe(true)
- // Batch should complete efficiently
- expect(totalDuration).toBeLessThan(150)
- // Results should be in original order
- expect(results[0].accountId).toBe('perf-pacifica')
- expect(results[1].accountId).toBe('perf-aster')
- expect(results[2].accountId).toBe('perf-binance')
- })
- })
- describe('High-Load Performance', () => {
- test('should maintain performance under high load', async () => {
- const message = new TextEncoder().encode('high load test')
- const operationCount = 50
- const operations = Array.from({ length: operationCount }, (_, i) => ({
- accountId: ['perf-pacifica', 'perf-aster', 'perf-binance'][i % 3],
- message
- }))
- const startTime = performance.now()
- const results = await Promise.all(
- operations.map(op => credentialManager.sign(op.accountId, op.message))
- )
- const totalDuration = performance.now() - startTime
- expect(results).toHaveLength(operationCount)
- expect(results.every(r => r.success)).toBe(true)
- // Should handle 50 operations efficiently
- expect(totalDuration).toBeLessThan(1000) // 1 second for 50 operations
- // Calculate percentiles
- const durations = results
- .map(r => r.metadata?.duration || 0)
- .sort((a, b) => a - b)
- const p50 = durations[Math.floor(durations.length * 0.5)]
- const p95 = durations[Math.floor(durations.length * 0.95)]
- const p99 = durations[Math.floor(durations.length * 0.99)]
- expect(p50).toBeLessThan(30) // 50th percentile < 30ms
- expect(p95).toBeLessThan(50) // 95th percentile < 50ms (requirement)
- expect(p99).toBeLessThan(75) // 99th percentile < 75ms (allows for outliers)
- })
- test('should handle sustained load without performance degradation', async () => {
- const message = new TextEncoder().encode('sustained load test')
- const batchSize = 10
- const batchCount = 5
- const batchResults: number[] = []
- for (let batch = 0; batch < batchCount; batch++) {
- const operations = Array.from({ length: batchSize }, (_, i) => ({
- accountId: ['perf-pacifica', 'perf-aster', 'perf-binance'][i % 3],
- message
- }))
- const batchStartTime = performance.now()
- const results = await Promise.all(
- operations.map(op => credentialManager.sign(op.accountId, op.message))
- )
- const batchDuration = performance.now() - batchStartTime
- expect(results.every(r => r.success)).toBe(true)
- batchResults.push(batchDuration)
- // Small delay between batches
- await new Promise(resolve => setTimeout(resolve, 10))
- }
- // Performance should not degrade significantly across batches
- const firstBatch = batchResults[0]
- const lastBatch = batchResults[batchResults.length - 1]
- // Last batch should not be more than 50% slower than first batch
- expect(lastBatch).toBeLessThan(firstBatch * 1.5)
- // All batches should complete within reasonable time
- batchResults.forEach(duration => {
- expect(duration).toBeLessThan(200) // 10 operations in 200ms
- })
- })
- })
- describe('Memory and Resource Performance', () => {
- test('should not leak memory during repeated operations', async () => {
- const message = new TextEncoder().encode('memory test')
- const initialMemory = process.memoryUsage()
- // Perform many signing operations
- for (let i = 0; i < 100; i++) {
- const accountId = ['perf-pacifica', 'perf-aster', 'perf-binance'][i % 3]
- const result = await credentialManager.sign(accountId, message)
- expect(result.success).toBe(true)
- }
- // Force garbage collection if available
- if (global.gc) {
- global.gc()
- await new Promise(resolve => setTimeout(resolve, 100))
- }
- const finalMemory = process.memoryUsage()
- // Memory increase should be reasonable (less than 10MB)
- const heapIncrease = finalMemory.heapUsed - initialMemory.heapUsed
- expect(heapIncrease).toBeLessThan(10 * 1024 * 1024) // 10MB
- })
- test('should maintain consistent performance across different message sizes', async () => {
- const messageSizes = [100, 1000, 10000, 100000] // bytes
- const performanceResults: Record<number, number[]> = {}
- for (const size of messageSizes) {
- const message = new TextEncoder().encode('x'.repeat(size))
- const durations: number[] = []
- // Test each size multiple times
- for (let i = 0; i < 10; i++) {
- const startTime = performance.now()
- const result = await credentialManager.sign('perf-pacifica', message)
- const duration = performance.now() - startTime
- expect(result.success).toBe(true)
- durations.push(duration)
- }
- performanceResults[size] = durations
- }
- // All message sizes should meet performance requirements
- Object.entries(performanceResults).forEach(([size, durations]) => {
- const averageDuration = durations.reduce((a, b) => a + b, 0) / durations.length
- const maxDuration = Math.max(...durations)
- expect(averageDuration).toBeLessThan(50) // Average < 50ms
- expect(maxDuration).toBeLessThan(100) // Max < 100ms (allowing for larger messages)
- })
- // Performance should scale reasonably with message size
- const avg100 = performanceResults[100].reduce((a, b) => a + b, 0) / 10
- const avg100k = performanceResults[100000].reduce((a, b) => a + b, 0) / 10
- // 1000x larger message should not be more than 10x slower
- expect(avg100k).toBeLessThan(avg100 * 10)
- })
- })
- describe('Platform-Specific Performance', () => {
- test('Ed25519 (Pacifica) should be fastest', async () => {
- const message = new TextEncoder().encode('ed25519 performance test')
- const iterations = 20
- const durations: number[] = []
- for (let i = 0; i < iterations; i++) {
- const startTime = performance.now()
- const result = await credentialManager.sign('perf-pacifica', message)
- const duration = performance.now() - startTime
- expect(result.success).toBe(true)
- durations.push(duration)
- }
- const averageDuration = durations.reduce((a, b) => a + b, 0) / iterations
- const maxDuration = Math.max(...durations)
- // Ed25519 should be very fast
- expect(averageDuration).toBeLessThan(20)
- expect(maxDuration).toBeLessThan(50)
- })
- test('ECDSA (Aster) should meet performance requirements', async () => {
- const message = new TextEncoder().encode('ecdsa performance test')
- const iterations = 20
- const durations: number[] = []
- for (let i = 0; i < iterations; i++) {
- const startTime = performance.now()
- const result = await credentialManager.sign('perf-aster', message)
- const duration = performance.now() - startTime
- expect(result.success).toBe(true)
- durations.push(duration)
- }
- const averageDuration = durations.reduce((a, b) => a + b, 0) / iterations
- const maxDuration = Math.max(...durations)
- // ECDSA should meet requirements
- expect(averageDuration).toBeLessThan(40)
- expect(maxDuration).toBeLessThan(50)
- })
- test('HMAC (Binance) should be very fast', async () => {
- const message = new TextEncoder().encode('hmac performance test')
- const iterations = 20
- const durations: number[] = []
- for (let i = 0; i < iterations; i++) {
- const startTime = performance.now()
- const result = await credentialManager.sign('perf-binance', message)
- const duration = performance.now() - startTime
- expect(result.success).toBe(true)
- durations.push(duration)
- }
- const averageDuration = durations.reduce((a, b) => a + b, 0) / iterations
- const maxDuration = Math.max(...durations)
- // HMAC should be fastest
- expect(averageDuration).toBeLessThan(10)
- expect(maxDuration).toBeLessThan(25)
- })
- })
- describe('Performance Metrics Collection', () => {
- test('should collect accurate performance metrics', async () => {
- const message = new TextEncoder().encode('metrics test')
- // Reset metrics
- unifiedSigner.resetMetrics()
- // Perform signing operations
- await unifiedSigner.sign('perf-pacifica', message, { collectMetrics: true })
- await unifiedSigner.sign('perf-aster', message, { collectMetrics: true })
- await unifiedSigner.sign('perf-binance', message, { collectMetrics: true })
- const metrics = unifiedSigner.getMetrics()
- expect(metrics.totalOperations).toBe(3)
- expect(metrics.successfulOperations).toBe(3)
- expect(metrics.failedOperations).toBe(0)
- expect(metrics.averageSigningTime).toBeGreaterThan(0)
- expect(metrics.averageSigningTime).toBeLessThan(50)
- // Platform-specific metrics
- expect(metrics.platformBreakdown[Platform.PACIFICA].operations).toBe(1)
- expect(metrics.platformBreakdown[Platform.ASTER].operations).toBe(1)
- expect(metrics.platformBreakdown[Platform.BINANCE].operations).toBe(1)
- expect(metrics.platformBreakdown[Platform.PACIFICA].successRate).toBe(1)
- expect(metrics.platformBreakdown[Platform.ASTER].successRate).toBe(1)
- expect(metrics.platformBreakdown[Platform.BINANCE].successRate).toBe(1)
- })
- test('should track performance degradation', async () => {
- const message = new TextEncoder().encode('degradation test')
- unifiedSigner.resetMetrics()
- // Perform operations and check if performance remains consistent
- const operationCount = 50
- const checkpoints = [10, 25, 50]
- const performanceAtCheckpoints: number[] = []
- for (let i = 1; i <= operationCount; i++) {
- const accountId = ['perf-pacifica', 'perf-aster', 'perf-binance'][i % 3]
- await unifiedSigner.sign(accountId, message, { collectMetrics: true })
- if (checkpoints.includes(i)) {
- const metrics = unifiedSigner.getMetrics()
- performanceAtCheckpoints.push(metrics.averageSigningTime)
- }
- }
- // Performance should not degrade significantly
- const [perf10, perf25, perf50] = performanceAtCheckpoints
- expect(perf10).toBeLessThan(50)
- expect(perf25).toBeLessThan(50)
- expect(perf50).toBeLessThan(50)
- // Performance at 50 operations should not be more than 50% worse than at 10
- expect(perf50).toBeLessThan(perf10 * 1.5)
- })
- })
- })
|