@morojs/moro 1.8.6 → 1.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/http/http-server.d.ts +5 -3
- package/dist/core/http/http-server.js +38 -11
- package/dist/core/http/http-server.js.map +1 -1
- package/dist/core/http/http2-server.d.ts +1 -1
- package/dist/core/http/http2-server.js +23 -9
- package/dist/core/http/http2-server.js.map +1 -1
- package/dist/core/http/moro-engine-server.d.ts +24 -4
- package/dist/core/http/moro-engine-server.js +194 -42
- package/dist/core/http/moro-engine-server.js.map +1 -1
- package/dist/core/pooling/object-pool-manager.js +14 -20
- package/dist/core/pooling/object-pool-manager.js.map +1 -1
- package/dist/core/routing/radix-tree.d.ts +1 -0
- package/dist/core/routing/radix-tree.js +6 -1
- package/dist/core/routing/radix-tree.js.map +1 -1
- package/dist/core/routing/unified-router.js +28 -25
- package/dist/core/routing/unified-router.js.map +1 -1
- package/dist/core/utilities/hooks.d.ts +2 -0
- package/dist/core/utilities/hooks.js +28 -2
- package/dist/core/utilities/hooks.js.map +1 -1
- package/dist/moro.js +12 -0
- package/dist/moro.js.map +1 -1
- package/package.json +1 -1
|
@@ -91,21 +91,19 @@ export class ObjectPoolManager {
|
|
|
91
91
|
const paramSize = sizes?.params ?? 50; // More aggressive default
|
|
92
92
|
const querySize = sizes?.query ?? 50;
|
|
93
93
|
const headerSize = sizes?.headers ?? 10;
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this.headerPool.release(obj);
|
|
108
|
-
}
|
|
94
|
+
// Acquire the full batch before releasing: an acquire immediately after a
|
|
95
|
+
// release just pops the object that was pushed, so an interleaved loop
|
|
96
|
+
// creates one object no matter the count
|
|
97
|
+
const warm = (pool, count) => {
|
|
98
|
+
const objs = new Array(count);
|
|
99
|
+
for (let i = 0; i < count; i++)
|
|
100
|
+
objs[i] = pool.acquire();
|
|
101
|
+
for (let i = 0; i < count; i++)
|
|
102
|
+
pool.release(objs[i]);
|
|
103
|
+
};
|
|
104
|
+
warm(this.paramPool, paramSize);
|
|
105
|
+
warm(this.queryPool, querySize);
|
|
106
|
+
warm(this.headerPool, headerSize);
|
|
109
107
|
// Pre-warm buffer pools with configurable sizes
|
|
110
108
|
const bufferSizes = sizes?.buffers ?? {};
|
|
111
109
|
const bufferSizesLen = this.bufferSizes.length;
|
|
@@ -115,11 +113,7 @@ export class ObjectPoolManager {
|
|
|
115
113
|
continue;
|
|
116
114
|
const pool = this.bufferPools.get(size);
|
|
117
115
|
if (pool) {
|
|
118
|
-
|
|
119
|
-
for (let j = 0; j < warmCount; j++) {
|
|
120
|
-
const buffer = pool.acquire();
|
|
121
|
-
pool.release(buffer);
|
|
122
|
-
}
|
|
116
|
+
warm(pool, bufferSizes[size] ?? Math.min(25, pool.stats.maxSize));
|
|
123
117
|
}
|
|
124
118
|
}
|
|
125
119
|
logger.debug('Object pools pre-warmed with optimal sizes', 'PoolManager', {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-pool-manager.js","sourceRoot":"","sources":["../../../src/core/pooling/object-pool-manager.ts"],"names":[],"mappings":"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","sourcesContent":["// Unified Object Pool Manager\n// Consolidates object pooling from http-server, router, and other components\n\nimport { createFrameworkLogger } from '../logger/index.js';\nimport * as crypto from 'crypto';\nimport { ObjectPool } from './object-pool.js';\nimport { LRUCache } from './lru-cache.js';\nconst logger = createFrameworkLogger('ObjectPoolManager');\n\n/**\n * ObjectPoolManager - Singleton for managing all object pools\n * Consolidates pools from:\n * - MoroHttpServer (paramObjectPool, bufferPool)\n * - Router (paramObjectPool)\n * - Various route caches\n */\nexport class ObjectPoolManager {\n private static instance: ObjectPoolManager | null = null;\n\n // Parameter object pool (for route params)\n private paramPool: ObjectPool<Record<string, string>>;\n\n // Header object pool (for parsed headers)\n private headerPool: ObjectPool<Record<string, string>>;\n\n // Query object pool (for parsed query strings)\n private queryPool: ObjectPool<Record<string, string>>;\n\n // Buffer pools by size\n private bufferPools: Map<number, ObjectPool<Buffer>>;\n private readonly bufferSizes = [64, 256, 1024, 4096, 16384];\n\n // Route lookup cache\n private routeCache: LRUCache<string, any>;\n\n // Response cache (for common responses - now includes full response metadata)\n private responseCache: LRUCache<\n string,\n { buffer: Buffer; headers: Record<string, string>; statusCode: number }\n >;\n\n // Performance monitoring\n private performanceStats = {\n poolHits: 0,\n poolMisses: 0,\n totalAcquisitions: 0,\n totalReleases: 0,\n lastAdjustment: 0,\n adjustmentInterval: 60000, // 1 minute\n };\n\n // Adaptive pool sizing\n private poolUsageHistory: Map<string, number[]> = new Map();\n private adaptiveMode = true;\n\n private constructor() {\n // Set initial last adjustment time to prevent immediate adjustment\n this.performanceStats.lastAdjustment = Date.now();\n\n // Initialize parameter object pool with adaptive sizing\n this.paramPool = new ObjectPool(\n () => ({}),\n 100, // Initial size\n (obj: Record<string, string>) => {\n // Clear all properties\n for (const key in obj) {\n delete obj[key];\n }\n }\n );\n\n // Initialize header object pool\n this.headerPool = new ObjectPool(\n () => ({}),\n 50, // Initial size - headers are less common to pool\n (obj: Record<string, string>) => {\n // Clear all properties\n for (const key in obj) {\n delete obj[key];\n }\n }\n );\n\n // Initialize query object pool\n this.queryPool = new ObjectPool(\n () => ({}),\n 100, // Initial size - queries are very common\n (obj: Record<string, string>) => {\n // Clear all properties\n for (const key in obj) {\n delete obj[key];\n }\n }\n );\n\n // Initialize buffer pools with enhanced sizing\n this.bufferPools = new Map();\n const bufferSizesLen = this.bufferSizes.length;\n for (let i = 0; i < bufferSizesLen; i++) {\n const size = this.bufferSizes[i];\n if (size === undefined) continue;\n this.bufferPools.set(\n size,\n new ObjectPool<Buffer>(() => Buffer.allocUnsafe(size), this.getOptimalPoolSize(size))\n );\n }\n\n // Initialize caches with enhanced statistics\n this.routeCache = new LRUCache(500);\n this.responseCache = new LRUCache(200); // Increased for full response caching\n\n // Pre-warm pools with optimal defaults\n this.preWarmPools();\n\n logger.debug(\n 'ObjectPoolManager initialized with enhanced performance features',\n 'Initialization'\n );\n }\n\n /**\n * Pre-warm pools with optimal sizes for better startup performance\n * Can be called with custom sizes to override defaults\n */\n preWarmPools(sizes?: {\n params?: number;\n query?: number;\n headers?: number;\n buffers?: Record<number, number>;\n }): void {\n // Aggressive pre-warming for common scenarios\n const paramSize = sizes?.params ?? 50; // More aggressive default\n const querySize = sizes?.query ?? 50;\n const headerSize = sizes?.headers ?? 10;\n\n // Pre-warm parameter pool\n for (let i = 0; i < paramSize; i++) {\n const obj = this.paramPool.acquire();\n this.paramPool.release(obj);\n }\n\n // Pre-warm query pool\n for (let i = 0; i < querySize; i++) {\n const obj = this.queryPool.acquire();\n this.queryPool.release(obj);\n }\n\n // Pre-warm header pool\n for (let i = 0; i < headerSize; i++) {\n const obj = this.headerPool.acquire();\n this.headerPool.release(obj);\n }\n\n // Pre-warm buffer pools with configurable sizes\n const bufferSizes = sizes?.buffers ?? {};\n const bufferSizesLen = this.bufferSizes.length;\n for (let i = 0; i < bufferSizesLen; i++) {\n const size = this.bufferSizes[i];\n if (size === undefined) continue;\n const pool = this.bufferPools.get(size);\n if (pool) {\n const warmCount = bufferSizes[size] ?? Math.min(25, pool.stats.maxSize);\n for (let j = 0; j < warmCount; j++) {\n const buffer = pool.acquire();\n pool.release(buffer);\n }\n }\n }\n\n logger.debug('Object pools pre-warmed with optimal sizes', 'PoolManager', {\n params: paramSize,\n query: querySize,\n headers: headerSize,\n });\n }\n\n /**\n * Get optimal pool size based on buffer size and usage patterns\n */\n private getOptimalPoolSize(bufferSize: number): number {\n // Smaller buffers can have larger pools\n if (bufferSize <= 256) return 100;\n if (bufferSize <= 1024) return 75;\n if (bufferSize <= 4096) return 50;\n return 25; // Large buffers need smaller pools\n }\n\n static getInstance(): ObjectPoolManager {\n if (!this.instance) {\n this.instance = new ObjectPoolManager();\n }\n return this.instance;\n }\n\n /**\n * Reset the singleton (useful for testing)\n */\n static reset(): void {\n if (this.instance) {\n this.instance.clearAll();\n }\n this.instance = null;\n }\n\n // Parameter Object Pool\n\n acquireParams(): Record<string, string> {\n this.performanceStats.totalAcquisitions++;\n const obj = this.paramPool.acquire();\n\n if (this.poolUsageHistory.has('params')) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const history = this.poolUsageHistory.get('params')!;\n if (history.length >= 100) {\n history.shift(); // Keep only last 100 measurements\n }\n history.push(this.paramPool.size);\n } else {\n this.poolUsageHistory.set('params', [this.paramPool.size]);\n }\n\n return obj;\n }\n\n releaseParams(obj: Record<string, string>): void {\n this.performanceStats.totalReleases++;\n this.paramPool.release(obj);\n\n // Adaptive pool sizing based on usage patterns\n if (\n this.adaptiveMode &&\n Date.now() - this.performanceStats.lastAdjustment > this.performanceStats.adjustmentInterval\n ) {\n this.adjustPoolSizes();\n }\n }\n\n // Header Object Pool\n\n acquireHeaders(): Record<string, string> {\n this.performanceStats.totalAcquisitions++;\n return this.headerPool.acquire();\n }\n\n releaseHeaders(obj: Record<string, string>): void {\n this.performanceStats.totalReleases++;\n this.headerPool.release(obj);\n }\n\n // Query Object Pool\n\n acquireQuery(): Record<string, string> {\n this.performanceStats.totalAcquisitions++;\n const obj = this.queryPool.acquire();\n\n const history = this.poolUsageHistory.get('query');\n if (history) {\n if (history.length >= 100) {\n history.shift();\n }\n history.push(this.queryPool.size);\n } else {\n this.poolUsageHistory.set('query', [this.queryPool.size]);\n }\n\n return obj;\n }\n\n releaseQuery(obj: Record<string, string>): void {\n this.performanceStats.totalReleases++;\n this.queryPool.release(obj);\n\n if (\n this.adaptiveMode &&\n Date.now() - this.performanceStats.lastAdjustment > this.performanceStats.adjustmentInterval\n ) {\n this.adjustPoolSizes();\n }\n }\n\n // Request ID Generation\n\n generateRequestId(): string {\n return crypto.randomUUID();\n }\n\n // Buffer Pool\n\n acquireBuffer(size: number): Buffer {\n this.performanceStats.totalAcquisitions++;\n\n // Find smallest buffer that fits\n for (const poolSize of this.bufferSizes) {\n if (size <= poolSize) {\n const pool = this.bufferPools.get(poolSize);\n if (pool) {\n const buffer = pool.acquire();\n this.performanceStats.poolHits++;\n\n // Track usage for adaptive sizing\n const poolKey = `buffer_${poolSize}`;\n if (this.poolUsageHistory.has(poolKey)) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const history = this.poolUsageHistory.get(poolKey)!;\n if (history.length >= 100) {\n history.shift();\n }\n history.push(pool.size);\n } else {\n this.poolUsageHistory.set(poolKey, [pool.size]);\n }\n\n return buffer;\n }\n }\n }\n\n // No pool available for this size, allocate directly\n this.performanceStats.poolMisses++;\n return Buffer.allocUnsafe(size);\n }\n\n releaseBuffer(buffer: Buffer): void {\n this.performanceStats.totalReleases++;\n const size = buffer.length;\n const pool = this.bufferPools.get(size);\n if (pool) {\n pool.release(buffer);\n\n // Adaptive pool sizing based on usage patterns\n if (\n this.adaptiveMode &&\n Date.now() - this.performanceStats.lastAdjustment > this.performanceStats.adjustmentInterval\n ) {\n this.adjustPoolSizes();\n }\n }\n // If no pool for this size, let it be garbage collected\n }\n\n // Route Cache\n\n getCachedRoute(key: string): any {\n return this.routeCache.get(key);\n }\n\n cacheRoute(key: string, route: any): void {\n this.routeCache.set(key, route);\n }\n\n hasCachedRoute(key: string): boolean {\n return this.routeCache.has(key);\n }\n\n clearRouteCache(): void {\n this.routeCache.clear();\n }\n\n // Response Cache (For Opt-In Explicit Caching Only)\n // NOTE: This cache is NOT used automatically by the framework.\n // It's available for developers who explicitly want to cache specific responses.\n // Developers must carefully manage cache keys to avoid stale/incorrect data.\n\n getCachedResponse(\n key: string\n ): { buffer: Buffer; headers: Record<string, string>; statusCode: number } | undefined {\n return this.responseCache.get(key);\n }\n\n cacheResponse(\n key: string,\n buffer: Buffer,\n headers: Record<string, string>,\n statusCode: number = 200\n ): void {\n // Cache responses up to 4KB\n // WARNING: Only use this for static responses that never change\n if (buffer.length < 4096) {\n this.responseCache.set(key, {\n buffer: Buffer.from(buffer), // Clone to avoid mutations\n headers: { ...headers }, // Clone headers\n statusCode,\n });\n }\n }\n\n hasCachedResponse(key: string): boolean {\n return this.responseCache.has(key);\n }\n\n clearResponseCache(): void {\n this.responseCache.clear();\n }\n\n /**\n * Adaptively adjust pool sizes based on usage patterns.\n * Each pool is sized to ~120% of its average observed size, clamped to a\n * [min, max] range, and only resized when the change exceeds a threshold.\n */\n private adjustPoolSizes(): void {\n this.performanceStats.lastAdjustment = Date.now();\n\n const applyFromHistory = (\n pool: ObjectPool<any>,\n historyKey: string,\n min: number,\n max: number,\n threshold: number,\n label: string\n ): void => {\n const history = this.poolUsageHistory.get(historyKey) || [];\n if (history.length < 10) return;\n\n const avgUsage = history.reduce((sum, size) => sum + size, 0) / history.length;\n const targetSize = Math.min(Math.max(Math.round(avgUsage * 1.2), min), max);\n\n if (Math.abs(pool.stats.maxSize - targetSize) > threshold) {\n logger.debug(\n `Adjusting ${label} pool size from ${pool.stats.maxSize} to ${targetSize}`,\n 'PoolManager'\n );\n pool.setMaxSize(targetSize);\n }\n };\n\n applyFromHistory(this.paramPool, 'params', 50, 200, 10, 'param');\n applyFromHistory(this.queryPool, 'query', 50, 200, 10, 'query');\n\n const bufferSizesLen = this.bufferSizes.length;\n for (let i = 0; i < bufferSizesLen; i++) {\n const size = this.bufferSizes[i];\n if (size === undefined) continue;\n const pool = this.bufferPools.get(size);\n if (!pool) continue;\n applyFromHistory(\n pool,\n `buffer_${size}`,\n 10,\n this.getOptimalPoolSize(size) * 2,\n 5,\n `buffer ${size}B`\n );\n }\n\n logger.debug('Pool size adjustment cycle completed', 'PoolManager');\n }\n\n /**\n * Enable or disable adaptive pool sizing\n */\n setAdaptiveMode(enabled: boolean): void {\n this.adaptiveMode = enabled;\n logger.debug(`Adaptive pool sizing ${enabled ? 'enabled' : 'disabled'}`, 'PoolManager');\n }\n\n // Utility Methods\n\n /**\n * Clear all pools and caches\n */\n clearAll(): void {\n this.paramPool.clear();\n this.headerPool.clear();\n this.queryPool.clear();\n this.bufferPools.forEach(pool => pool.clear());\n this.routeCache.clear();\n this.responseCache.clear();\n logger.debug('All pools and caches cleared', 'Maintenance');\n }\n\n /**\n * Force garbage collection on pooled objects\n */\n forceCleanup(): void {\n this.clearAll();\n\n // Force GC if available\n if (globalThis?.gc) {\n globalThis.gc();\n logger.debug('Forced garbage collection', 'Maintenance');\n }\n }\n\n /**\n * Get comprehensive performance statistics\n */\n getStats() {\n const bufferPoolStats: Record<string, any> = {};\n this.bufferPools.forEach((pool, size) => {\n bufferPoolStats[`${size}B`] = pool.stats;\n });\n\n return {\n paramPool: this.paramPool.stats,\n headerPool: this.headerPool.stats,\n queryPool: this.queryPool.stats,\n bufferPools: bufferPoolStats,\n routeCache: this.routeCache.stats,\n responseCache: this.responseCache.stats,\n totalMemory: {\n params: this.paramPool.size * 50, // Rough estimate\n headers: this.headerPool.size * 100, // Rough estimate\n queries: this.queryPool.size * 50, // Rough estimate\n buffers: Array.from(this.bufferPools.values()).reduce((sum, pool) => sum + pool.size, 0),\n routes: this.routeCache.size * 200, // Rough estimate\n responses: this.responseCache.size * 1000, // Rough estimate (increased for full responses)\n },\n };\n }\n\n /**\n * Get performance summary for monitoring\n */\n getPerformanceSummary() {\n const stats = this.getStats();\n const routeCacheTotal = stats.routeCache.hits + stats.routeCache.misses;\n const responseCacheTotal = stats.responseCache.hits + stats.responseCache.misses;\n\n // Manually sum memory instead of Object.values().reduce()\n let totalMemory = 0;\n totalMemory += stats.totalMemory.params;\n totalMemory += stats.totalMemory.headers;\n totalMemory += stats.totalMemory.queries;\n totalMemory += stats.totalMemory.buffers;\n totalMemory += stats.totalMemory.routes;\n totalMemory += stats.totalMemory.responses;\n\n return {\n routeCacheHitRate: routeCacheTotal > 0 ? (stats.routeCache.hits / routeCacheTotal) * 100 : 0,\n responseCacheHitRate:\n responseCacheTotal > 0 ? (stats.responseCache.hits / responseCacheTotal) * 100 : 0,\n paramPoolUtilization: stats.paramPool.utilization * 100,\n totalMemoryKB: totalMemory / 1024,\n };\n }\n\n /**\n * Log performance statistics\n */\n logStats(): void {\n const summary = this.getPerformanceSummary();\n logger.info('ObjectPoolManager Performance', 'Stats', {\n routeCacheHitRate: `${summary.routeCacheHitRate.toFixed(1)}%`,\n responseCacheHitRate: `${summary.responseCacheHitRate.toFixed(1)}%`,\n paramPoolUtilization: `${summary.paramPoolUtilization.toFixed(1)}%`,\n totalMemory: `${summary.totalMemoryKB.toFixed(1)} KB`,\n });\n }\n}\n\n/**\n * Convenience function to get the singleton instance\n */\nexport function getPoolManager(): ObjectPoolManager {\n return ObjectPoolManager.getInstance();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"object-pool-manager.js","sourceRoot":"","sources":["../../../src/core/pooling/object-pool-manager.ts"],"names":[],"mappings":"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","sourcesContent":["// Unified Object Pool Manager\n// Consolidates object pooling from http-server, router, and other components\n\nimport { createFrameworkLogger } from '../logger/index.js';\nimport * as crypto from 'crypto';\nimport { ObjectPool } from './object-pool.js';\nimport { LRUCache } from './lru-cache.js';\nconst logger = createFrameworkLogger('ObjectPoolManager');\n\n/**\n * ObjectPoolManager - Singleton for managing all object pools\n * Consolidates pools from:\n * - MoroHttpServer (paramObjectPool, bufferPool)\n * - Router (paramObjectPool)\n * - Various route caches\n */\nexport class ObjectPoolManager {\n private static instance: ObjectPoolManager | null = null;\n\n // Parameter object pool (for route params)\n private paramPool: ObjectPool<Record<string, string>>;\n\n // Header object pool (for parsed headers)\n private headerPool: ObjectPool<Record<string, string>>;\n\n // Query object pool (for parsed query strings)\n private queryPool: ObjectPool<Record<string, string>>;\n\n // Buffer pools by size\n private bufferPools: Map<number, ObjectPool<Buffer>>;\n private readonly bufferSizes = [64, 256, 1024, 4096, 16384];\n\n // Route lookup cache\n private routeCache: LRUCache<string, any>;\n\n // Response cache (for common responses - now includes full response metadata)\n private responseCache: LRUCache<\n string,\n { buffer: Buffer; headers: Record<string, string>; statusCode: number }\n >;\n\n // Performance monitoring\n private performanceStats = {\n poolHits: 0,\n poolMisses: 0,\n totalAcquisitions: 0,\n totalReleases: 0,\n lastAdjustment: 0,\n adjustmentInterval: 60000, // 1 minute\n };\n\n // Adaptive pool sizing\n private poolUsageHistory: Map<string, number[]> = new Map();\n private adaptiveMode = true;\n\n private constructor() {\n // Set initial last adjustment time to prevent immediate adjustment\n this.performanceStats.lastAdjustment = Date.now();\n\n // Initialize parameter object pool with adaptive sizing\n this.paramPool = new ObjectPool(\n () => ({}),\n 100, // Initial size\n (obj: Record<string, string>) => {\n // Clear all properties\n for (const key in obj) {\n delete obj[key];\n }\n }\n );\n\n // Initialize header object pool\n this.headerPool = new ObjectPool(\n () => ({}),\n 50, // Initial size - headers are less common to pool\n (obj: Record<string, string>) => {\n // Clear all properties\n for (const key in obj) {\n delete obj[key];\n }\n }\n );\n\n // Initialize query object pool\n this.queryPool = new ObjectPool(\n () => ({}),\n 100, // Initial size - queries are very common\n (obj: Record<string, string>) => {\n // Clear all properties\n for (const key in obj) {\n delete obj[key];\n }\n }\n );\n\n // Initialize buffer pools with enhanced sizing\n this.bufferPools = new Map();\n const bufferSizesLen = this.bufferSizes.length;\n for (let i = 0; i < bufferSizesLen; i++) {\n const size = this.bufferSizes[i];\n if (size === undefined) continue;\n this.bufferPools.set(\n size,\n new ObjectPool<Buffer>(() => Buffer.allocUnsafe(size), this.getOptimalPoolSize(size))\n );\n }\n\n // Initialize caches with enhanced statistics\n this.routeCache = new LRUCache(500);\n this.responseCache = new LRUCache(200); // Increased for full response caching\n\n // Pre-warm pools with optimal defaults\n this.preWarmPools();\n\n logger.debug(\n 'ObjectPoolManager initialized with enhanced performance features',\n 'Initialization'\n );\n }\n\n /**\n * Pre-warm pools with optimal sizes for better startup performance\n * Can be called with custom sizes to override defaults\n */\n preWarmPools(sizes?: {\n params?: number;\n query?: number;\n headers?: number;\n buffers?: Record<number, number>;\n }): void {\n // Aggressive pre-warming for common scenarios\n const paramSize = sizes?.params ?? 50; // More aggressive default\n const querySize = sizes?.query ?? 50;\n const headerSize = sizes?.headers ?? 10;\n\n // Acquire the full batch before releasing: an acquire immediately after a\n // release just pops the object that was pushed, so an interleaved loop\n // creates one object no matter the count\n const warm = <T>(pool: { acquire(): T; release(obj: T): void }, count: number): void => {\n const objs: T[] = new Array(count);\n for (let i = 0; i < count; i++) objs[i] = pool.acquire();\n for (let i = 0; i < count; i++) pool.release(objs[i] as T);\n };\n\n warm(this.paramPool, paramSize);\n warm(this.queryPool, querySize);\n warm(this.headerPool, headerSize);\n\n // Pre-warm buffer pools with configurable sizes\n const bufferSizes = sizes?.buffers ?? {};\n const bufferSizesLen = this.bufferSizes.length;\n for (let i = 0; i < bufferSizesLen; i++) {\n const size = this.bufferSizes[i];\n if (size === undefined) continue;\n const pool = this.bufferPools.get(size);\n if (pool) {\n warm(pool, bufferSizes[size] ?? Math.min(25, pool.stats.maxSize));\n }\n }\n\n logger.debug('Object pools pre-warmed with optimal sizes', 'PoolManager', {\n params: paramSize,\n query: querySize,\n headers: headerSize,\n });\n }\n\n /**\n * Get optimal pool size based on buffer size and usage patterns\n */\n private getOptimalPoolSize(bufferSize: number): number {\n // Smaller buffers can have larger pools\n if (bufferSize <= 256) return 100;\n if (bufferSize <= 1024) return 75;\n if (bufferSize <= 4096) return 50;\n return 25; // Large buffers need smaller pools\n }\n\n static getInstance(): ObjectPoolManager {\n if (!this.instance) {\n this.instance = new ObjectPoolManager();\n }\n return this.instance;\n }\n\n /**\n * Reset the singleton (useful for testing)\n */\n static reset(): void {\n if (this.instance) {\n this.instance.clearAll();\n }\n this.instance = null;\n }\n\n // Parameter Object Pool\n\n acquireParams(): Record<string, string> {\n this.performanceStats.totalAcquisitions++;\n const obj = this.paramPool.acquire();\n\n if (this.poolUsageHistory.has('params')) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const history = this.poolUsageHistory.get('params')!;\n if (history.length >= 100) {\n history.shift(); // Keep only last 100 measurements\n }\n history.push(this.paramPool.size);\n } else {\n this.poolUsageHistory.set('params', [this.paramPool.size]);\n }\n\n return obj;\n }\n\n releaseParams(obj: Record<string, string>): void {\n this.performanceStats.totalReleases++;\n this.paramPool.release(obj);\n\n // Adaptive pool sizing based on usage patterns\n if (\n this.adaptiveMode &&\n Date.now() - this.performanceStats.lastAdjustment > this.performanceStats.adjustmentInterval\n ) {\n this.adjustPoolSizes();\n }\n }\n\n // Header Object Pool\n\n acquireHeaders(): Record<string, string> {\n this.performanceStats.totalAcquisitions++;\n return this.headerPool.acquire();\n }\n\n releaseHeaders(obj: Record<string, string>): void {\n this.performanceStats.totalReleases++;\n this.headerPool.release(obj);\n }\n\n // Query Object Pool\n\n acquireQuery(): Record<string, string> {\n this.performanceStats.totalAcquisitions++;\n const obj = this.queryPool.acquire();\n\n const history = this.poolUsageHistory.get('query');\n if (history) {\n if (history.length >= 100) {\n history.shift();\n }\n history.push(this.queryPool.size);\n } else {\n this.poolUsageHistory.set('query', [this.queryPool.size]);\n }\n\n return obj;\n }\n\n releaseQuery(obj: Record<string, string>): void {\n this.performanceStats.totalReleases++;\n this.queryPool.release(obj);\n\n if (\n this.adaptiveMode &&\n Date.now() - this.performanceStats.lastAdjustment > this.performanceStats.adjustmentInterval\n ) {\n this.adjustPoolSizes();\n }\n }\n\n // Request ID Generation\n\n generateRequestId(): string {\n return crypto.randomUUID();\n }\n\n // Buffer Pool\n\n acquireBuffer(size: number): Buffer {\n this.performanceStats.totalAcquisitions++;\n\n // Find smallest buffer that fits\n for (const poolSize of this.bufferSizes) {\n if (size <= poolSize) {\n const pool = this.bufferPools.get(poolSize);\n if (pool) {\n const buffer = pool.acquire();\n this.performanceStats.poolHits++;\n\n // Track usage for adaptive sizing\n const poolKey = `buffer_${poolSize}`;\n if (this.poolUsageHistory.has(poolKey)) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const history = this.poolUsageHistory.get(poolKey)!;\n if (history.length >= 100) {\n history.shift();\n }\n history.push(pool.size);\n } else {\n this.poolUsageHistory.set(poolKey, [pool.size]);\n }\n\n return buffer;\n }\n }\n }\n\n // No pool available for this size, allocate directly\n this.performanceStats.poolMisses++;\n return Buffer.allocUnsafe(size);\n }\n\n releaseBuffer(buffer: Buffer): void {\n this.performanceStats.totalReleases++;\n const size = buffer.length;\n const pool = this.bufferPools.get(size);\n if (pool) {\n pool.release(buffer);\n\n // Adaptive pool sizing based on usage patterns\n if (\n this.adaptiveMode &&\n Date.now() - this.performanceStats.lastAdjustment > this.performanceStats.adjustmentInterval\n ) {\n this.adjustPoolSizes();\n }\n }\n // If no pool for this size, let it be garbage collected\n }\n\n // Route Cache\n\n getCachedRoute(key: string): any {\n return this.routeCache.get(key);\n }\n\n cacheRoute(key: string, route: any): void {\n this.routeCache.set(key, route);\n }\n\n hasCachedRoute(key: string): boolean {\n return this.routeCache.has(key);\n }\n\n clearRouteCache(): void {\n this.routeCache.clear();\n }\n\n // Response Cache (For Opt-In Explicit Caching Only)\n // NOTE: This cache is NOT used automatically by the framework.\n // It's available for developers who explicitly want to cache specific responses.\n // Developers must carefully manage cache keys to avoid stale/incorrect data.\n\n getCachedResponse(\n key: string\n ): { buffer: Buffer; headers: Record<string, string>; statusCode: number } | undefined {\n return this.responseCache.get(key);\n }\n\n cacheResponse(\n key: string,\n buffer: Buffer,\n headers: Record<string, string>,\n statusCode: number = 200\n ): void {\n // Cache responses up to 4KB\n // WARNING: Only use this for static responses that never change\n if (buffer.length < 4096) {\n this.responseCache.set(key, {\n buffer: Buffer.from(buffer), // Clone to avoid mutations\n headers: { ...headers }, // Clone headers\n statusCode,\n });\n }\n }\n\n hasCachedResponse(key: string): boolean {\n return this.responseCache.has(key);\n }\n\n clearResponseCache(): void {\n this.responseCache.clear();\n }\n\n /**\n * Adaptively adjust pool sizes based on usage patterns.\n * Each pool is sized to ~120% of its average observed size, clamped to a\n * [min, max] range, and only resized when the change exceeds a threshold.\n */\n private adjustPoolSizes(): void {\n this.performanceStats.lastAdjustment = Date.now();\n\n const applyFromHistory = (\n pool: ObjectPool<any>,\n historyKey: string,\n min: number,\n max: number,\n threshold: number,\n label: string\n ): void => {\n const history = this.poolUsageHistory.get(historyKey) || [];\n if (history.length < 10) return;\n\n const avgUsage = history.reduce((sum, size) => sum + size, 0) / history.length;\n const targetSize = Math.min(Math.max(Math.round(avgUsage * 1.2), min), max);\n\n if (Math.abs(pool.stats.maxSize - targetSize) > threshold) {\n logger.debug(\n `Adjusting ${label} pool size from ${pool.stats.maxSize} to ${targetSize}`,\n 'PoolManager'\n );\n pool.setMaxSize(targetSize);\n }\n };\n\n applyFromHistory(this.paramPool, 'params', 50, 200, 10, 'param');\n applyFromHistory(this.queryPool, 'query', 50, 200, 10, 'query');\n\n const bufferSizesLen = this.bufferSizes.length;\n for (let i = 0; i < bufferSizesLen; i++) {\n const size = this.bufferSizes[i];\n if (size === undefined) continue;\n const pool = this.bufferPools.get(size);\n if (!pool) continue;\n applyFromHistory(\n pool,\n `buffer_${size}`,\n 10,\n this.getOptimalPoolSize(size) * 2,\n 5,\n `buffer ${size}B`\n );\n }\n\n logger.debug('Pool size adjustment cycle completed', 'PoolManager');\n }\n\n /**\n * Enable or disable adaptive pool sizing\n */\n setAdaptiveMode(enabled: boolean): void {\n this.adaptiveMode = enabled;\n logger.debug(`Adaptive pool sizing ${enabled ? 'enabled' : 'disabled'}`, 'PoolManager');\n }\n\n // Utility Methods\n\n /**\n * Clear all pools and caches\n */\n clearAll(): void {\n this.paramPool.clear();\n this.headerPool.clear();\n this.queryPool.clear();\n this.bufferPools.forEach(pool => pool.clear());\n this.routeCache.clear();\n this.responseCache.clear();\n logger.debug('All pools and caches cleared', 'Maintenance');\n }\n\n /**\n * Force garbage collection on pooled objects\n */\n forceCleanup(): void {\n this.clearAll();\n\n // Force GC if available\n if (globalThis?.gc) {\n globalThis.gc();\n logger.debug('Forced garbage collection', 'Maintenance');\n }\n }\n\n /**\n * Get comprehensive performance statistics\n */\n getStats() {\n const bufferPoolStats: Record<string, any> = {};\n this.bufferPools.forEach((pool, size) => {\n bufferPoolStats[`${size}B`] = pool.stats;\n });\n\n return {\n paramPool: this.paramPool.stats,\n headerPool: this.headerPool.stats,\n queryPool: this.queryPool.stats,\n bufferPools: bufferPoolStats,\n routeCache: this.routeCache.stats,\n responseCache: this.responseCache.stats,\n totalMemory: {\n params: this.paramPool.size * 50, // Rough estimate\n headers: this.headerPool.size * 100, // Rough estimate\n queries: this.queryPool.size * 50, // Rough estimate\n buffers: Array.from(this.bufferPools.values()).reduce((sum, pool) => sum + pool.size, 0),\n routes: this.routeCache.size * 200, // Rough estimate\n responses: this.responseCache.size * 1000, // Rough estimate (increased for full responses)\n },\n };\n }\n\n /**\n * Get performance summary for monitoring\n */\n getPerformanceSummary() {\n const stats = this.getStats();\n const routeCacheTotal = stats.routeCache.hits + stats.routeCache.misses;\n const responseCacheTotal = stats.responseCache.hits + stats.responseCache.misses;\n\n // Manually sum memory instead of Object.values().reduce()\n let totalMemory = 0;\n totalMemory += stats.totalMemory.params;\n totalMemory += stats.totalMemory.headers;\n totalMemory += stats.totalMemory.queries;\n totalMemory += stats.totalMemory.buffers;\n totalMemory += stats.totalMemory.routes;\n totalMemory += stats.totalMemory.responses;\n\n return {\n routeCacheHitRate: routeCacheTotal > 0 ? (stats.routeCache.hits / routeCacheTotal) * 100 : 0,\n responseCacheHitRate:\n responseCacheTotal > 0 ? (stats.responseCache.hits / responseCacheTotal) * 100 : 0,\n paramPoolUtilization: stats.paramPool.utilization * 100,\n totalMemoryKB: totalMemory / 1024,\n };\n }\n\n /**\n * Log performance statistics\n */\n logStats(): void {\n const summary = this.getPerformanceSummary();\n logger.info('ObjectPoolManager Performance', 'Stats', {\n routeCacheHitRate: `${summary.routeCacheHitRate.toFixed(1)}%`,\n responseCacheHitRate: `${summary.responseCacheHitRate.toFixed(1)}%`,\n paramPoolUtilization: `${summary.paramPoolUtilization.toFixed(1)}%`,\n totalMemory: `${summary.totalMemoryKB.toFixed(1)} KB`,\n });\n }\n}\n\n/**\n * Convenience function to get the singleton instance\n */\nexport function getPoolManager(): ObjectPoolManager {\n return ObjectPoolManager.getInstance();\n}\n"]}
|
|
@@ -30,6 +30,8 @@ function segmentEqualsRange(segment, path, start, end) {
|
|
|
30
30
|
}
|
|
31
31
|
export class RadixTree {
|
|
32
32
|
root;
|
|
33
|
+
// Scratch buffer for search() - see the comment there before touching
|
|
34
|
+
paramScratch = [];
|
|
33
35
|
constructor() {
|
|
34
36
|
this.root = {
|
|
35
37
|
segmentHash: 0,
|
|
@@ -159,7 +161,10 @@ export class RadixTree {
|
|
|
159
161
|
* Search for a route in the radix tree - HASH-BASED
|
|
160
162
|
*/
|
|
161
163
|
search(path) {
|
|
162
|
-
|
|
164
|
+
// Reused across calls: search is synchronous and the values are copied
|
|
165
|
+
// into the fresh params object below before returning, so nothing escapes
|
|
166
|
+
const paramValues = this.paramScratch;
|
|
167
|
+
paramValues.length = 0;
|
|
163
168
|
const result = this.searchNode(this.root, path, 0, paramValues);
|
|
164
169
|
if (result) {
|
|
165
170
|
// Build params object using stored parameter names from the matched route
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"radix-tree.js","sourceRoot":"","sources":["../../../src/core/routing/radix-tree.ts"],"names":[],"mappings":"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","sourcesContent":["// High-performance Radix Tree for dynamic route matching\n\nexport interface RadixNode {\n // Store hash for faster lookups\n segmentHash: number;\n segment: string;\n staticChildren: Map<number, RadixNode> | null; // Hash-based lookup\n paramChild: RadixNode | null;\n paramName: string | null;\n handler: any;\n // Store parameter names for this specific handler/route\n paramPath: string[] | null;\n // Sibling chain for FNV hash collisions (segments with equal hash, different text)\n collisionNext: RadixNode | null;\n}\n\nexport interface MatchResult {\n handler: any;\n params: Record<string, string>;\n}\n\n// Fast hash function for path segments (FNV-1a inspired)\nfunction fastHash(str: string): number {\n let hash = 0x811c9dc5; // FNV offset basis\n const len = str.length;\n\n for (let i = 0; i < len; i++) {\n hash ^= str.charCodeAt(i);\n hash = (hash * 0x01000193) >>> 0; // FNV prime (32-bit)\n }\n\n return hash;\n}\n\n// Same hash computed over a path slice without allocating the substring\nfunction fastHashRange(path: string, start: number, end: number): number {\n let hash = 0x811c9dc5;\n for (let i = start; i < end; i++) {\n hash ^= path.charCodeAt(i);\n hash = (hash * 0x01000193) >>> 0;\n }\n return hash;\n}\n\n// Compare a stored segment against a path slice without allocating\nfunction segmentEqualsRange(segment: string, path: string, start: number, end: number): boolean {\n if (segment.length !== end - start) return false;\n for (let i = start; i < end; i++) {\n if (segment.charCodeAt(i - start) !== path.charCodeAt(i)) return false;\n }\n return true;\n}\n\nexport class RadixTree {\n private root: RadixNode;\n\n constructor() {\n this.root = {\n segmentHash: 0,\n segment: '',\n staticChildren: null,\n paramChild: null,\n paramName: null,\n handler: null,\n paramPath: null,\n collisionNext: null,\n };\n }\n\n /**\n * Insert a route into the radix tree - HASH-BASED\n */\n insert(path: string, handler: any): void {\n let node = this.root;\n let i = 0;\n const len = path.length;\n const paramNames: string[] = [];\n\n // Skip leading slash\n if (len > 0 && path.charCodeAt(0) === 47) {\n i = 1;\n }\n\n while (i < len) {\n const charCode = path.charCodeAt(i);\n\n // Skip any additional slashes\n if (charCode === 47) {\n i++;\n continue;\n }\n\n // Check for parameter (58 = ':')\n if (charCode === 58) {\n // Find end of parameter name (47 = '/')\n let end = i + 1;\n while (end < len && path.charCodeAt(end) !== 47) {\n end++;\n }\n\n const paramName = path.slice(i + 1, end);\n paramNames.push(paramName);\n\n // Create param child if needed\n if (!node.paramChild) {\n node.paramChild = {\n segmentHash: 0,\n segment: '',\n staticChildren: null,\n paramChild: null,\n paramName: paramName,\n handler: null,\n paramPath: null,\n collisionNext: null,\n };\n }\n\n node = node.paramChild;\n i = end;\n continue;\n }\n\n // Find end of static segment (up to next '/' or ':')\n let segEnd = i + 1;\n while (segEnd < len) {\n const code = path.charCodeAt(segEnd);\n if (code === 47 || code === 58) break; // '/' or ':'\n segEnd++;\n }\n const segment = path.slice(i, segEnd);\n const segmentHash = fastHash(segment);\n\n // Lazy initialization of staticChildren (hash-based)\n if (!node.staticChildren) {\n node.staticChildren = new Map();\n const child: RadixNode = {\n segmentHash,\n segment,\n staticChildren: null,\n paramChild: null,\n paramName: null,\n handler: null,\n paramPath: null,\n collisionNext: null,\n };\n node.staticChildren.set(segmentHash, child);\n node = child;\n } else {\n let child = node.staticChildren.get(segmentHash);\n if (!child) {\n child = {\n segmentHash,\n segment,\n staticChildren: null,\n paramChild: null,\n paramName: null,\n handler: null,\n paramPath: null,\n collisionNext: null,\n };\n node.staticChildren.set(segmentHash, child);\n } else {\n // FNV hash collision: walk the sibling chain for a true segment match,\n // appending a new node if this exact segment isn't chained yet\n while (child.segment !== segment) {\n if (!child.collisionNext) {\n child.collisionNext = {\n segmentHash,\n segment,\n staticChildren: null,\n paramChild: null,\n paramName: null,\n handler: null,\n paramPath: null,\n collisionNext: null,\n };\n }\n child = child.collisionNext;\n }\n }\n node = child;\n }\n\n i = segEnd;\n }\n\n // Store handler and parameter names for this specific route\n node.handler = handler;\n node.paramPath = paramNames.length > 0 ? paramNames : null;\n }\n\n /**\n * Search for a route in the radix tree - HASH-BASED\n */\n search(path: string): MatchResult | null {\n const paramValues: string[] = [];\n const result = this.searchNode(this.root, path, 0, paramValues);\n\n if (result) {\n // Build params object using stored parameter names from the matched route\n const params: Record<string, string> = {};\n if (result.paramPath) {\n for (let i = 0; i < result.paramPath.length; i++) {\n params[result.paramPath[i] as string] = paramValues[i] as string;\n }\n }\n return { handler: result.handler, params };\n }\n\n return null;\n }\n\n private searchNode(\n node: RadixNode,\n path: string,\n idx: number,\n paramValues: string[]\n ): RadixNode | null {\n const len = path.length;\n\n // Skip slashes\n while (idx < len && path.charCodeAt(idx) === 47) {\n idx++;\n }\n\n // End of path - return node if it has a handler\n if (idx === len) {\n return node.handler ? node : null;\n }\n\n // Try static children first (fastest) - hash-based lookup\n if (node.staticChildren) {\n // Extract current segment and compute hash (until next '/' or end)\n let segEnd = idx;\n const slashCode = 47; // '/'\n while (segEnd < len && path.charCodeAt(segEnd) !== slashCode) {\n segEnd++;\n }\n // Hash and compare in place - no substring allocation per segment\n const segmentHash = fastHashRange(path, idx, segEnd);\n\n // Direct hash lookup (O(1)), walking the collision chain if needed\n let child: RadixNode | null | undefined = node.staticChildren.get(segmentHash);\n while (child && !segmentEqualsRange(child.segment, path, idx, segEnd)) {\n child = child.collisionNext;\n }\n if (child) {\n const result = this.searchNode(child, path, segEnd, paramValues);\n if (result) {\n return result;\n }\n }\n }\n\n // Try parameter child\n if (node.paramChild) {\n // Find end of param value (next '/' or end of path)\n let end = idx;\n const slashCode = 47; // '/'\n while (end < len && path.charCodeAt(end) !== slashCode) {\n end++;\n }\n\n if (end > idx) {\n const paramValue = path.slice(idx, end);\n paramValues.push(paramValue);\n\n const result = this.searchNode(node.paramChild, path, end, paramValues);\n if (result) {\n return result;\n }\n\n // Backtrack if no match\n paramValues.pop();\n }\n }\n\n return null;\n }\n\n /**\n * Clear the tree\n */\n clear(): void {\n this.root = {\n segmentHash: 0,\n segment: '',\n staticChildren: null,\n paramChild: null,\n paramName: null,\n handler: null,\n paramPath: null,\n collisionNext: null,\n };\n }\n}\n\n/**\n * Method-specific radix tree router\n */\nexport class MethodRadixRouter {\n private trees: Map<string, RadixTree>;\n\n constructor() {\n this.trees = new Map();\n }\n\n /**\n * Add a route - OPTIMIZED\n */\n addRoute(method: string, path: string, handler: any): void {\n let tree = this.trees.get(method);\n if (!tree) {\n tree = new RadixTree();\n this.trees.set(method, tree);\n }\n tree.insert(path, handler);\n }\n\n /**\n * Find a route - OPTIMIZED\n */\n findRoute(method: string, path: string): MatchResult | null {\n const tree = this.trees.get(method);\n return tree ? tree.search(path) : null;\n }\n\n /**\n * Clear all routes\n */\n clear(): void {\n this.trees.clear();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"radix-tree.js","sourceRoot":"","sources":["../../../src/core/routing/radix-tree.ts"],"names":[],"mappings":"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","sourcesContent":["// High-performance Radix Tree for dynamic route matching\n\nexport interface RadixNode {\n // Store hash for faster lookups\n segmentHash: number;\n segment: string;\n staticChildren: Map<number, RadixNode> | null; // Hash-based lookup\n paramChild: RadixNode | null;\n paramName: string | null;\n handler: any;\n // Store parameter names for this specific handler/route\n paramPath: string[] | null;\n // Sibling chain for FNV hash collisions (segments with equal hash, different text)\n collisionNext: RadixNode | null;\n}\n\nexport interface MatchResult {\n handler: any;\n params: Record<string, string>;\n}\n\n// Fast hash function for path segments (FNV-1a inspired)\nfunction fastHash(str: string): number {\n let hash = 0x811c9dc5; // FNV offset basis\n const len = str.length;\n\n for (let i = 0; i < len; i++) {\n hash ^= str.charCodeAt(i);\n hash = (hash * 0x01000193) >>> 0; // FNV prime (32-bit)\n }\n\n return hash;\n}\n\n// Same hash computed over a path slice without allocating the substring\nfunction fastHashRange(path: string, start: number, end: number): number {\n let hash = 0x811c9dc5;\n for (let i = start; i < end; i++) {\n hash ^= path.charCodeAt(i);\n hash = (hash * 0x01000193) >>> 0;\n }\n return hash;\n}\n\n// Compare a stored segment against a path slice without allocating\nfunction segmentEqualsRange(segment: string, path: string, start: number, end: number): boolean {\n if (segment.length !== end - start) return false;\n for (let i = start; i < end; i++) {\n if (segment.charCodeAt(i - start) !== path.charCodeAt(i)) return false;\n }\n return true;\n}\n\nexport class RadixTree {\n private root: RadixNode;\n // Scratch buffer for search() - see the comment there before touching\n private readonly paramScratch: string[] = [];\n\n constructor() {\n this.root = {\n segmentHash: 0,\n segment: '',\n staticChildren: null,\n paramChild: null,\n paramName: null,\n handler: null,\n paramPath: null,\n collisionNext: null,\n };\n }\n\n /**\n * Insert a route into the radix tree - HASH-BASED\n */\n insert(path: string, handler: any): void {\n let node = this.root;\n let i = 0;\n const len = path.length;\n const paramNames: string[] = [];\n\n // Skip leading slash\n if (len > 0 && path.charCodeAt(0) === 47) {\n i = 1;\n }\n\n while (i < len) {\n const charCode = path.charCodeAt(i);\n\n // Skip any additional slashes\n if (charCode === 47) {\n i++;\n continue;\n }\n\n // Check for parameter (58 = ':')\n if (charCode === 58) {\n // Find end of parameter name (47 = '/')\n let end = i + 1;\n while (end < len && path.charCodeAt(end) !== 47) {\n end++;\n }\n\n const paramName = path.slice(i + 1, end);\n paramNames.push(paramName);\n\n // Create param child if needed\n if (!node.paramChild) {\n node.paramChild = {\n segmentHash: 0,\n segment: '',\n staticChildren: null,\n paramChild: null,\n paramName: paramName,\n handler: null,\n paramPath: null,\n collisionNext: null,\n };\n }\n\n node = node.paramChild;\n i = end;\n continue;\n }\n\n // Find end of static segment (up to next '/' or ':')\n let segEnd = i + 1;\n while (segEnd < len) {\n const code = path.charCodeAt(segEnd);\n if (code === 47 || code === 58) break; // '/' or ':'\n segEnd++;\n }\n const segment = path.slice(i, segEnd);\n const segmentHash = fastHash(segment);\n\n // Lazy initialization of staticChildren (hash-based)\n if (!node.staticChildren) {\n node.staticChildren = new Map();\n const child: RadixNode = {\n segmentHash,\n segment,\n staticChildren: null,\n paramChild: null,\n paramName: null,\n handler: null,\n paramPath: null,\n collisionNext: null,\n };\n node.staticChildren.set(segmentHash, child);\n node = child;\n } else {\n let child = node.staticChildren.get(segmentHash);\n if (!child) {\n child = {\n segmentHash,\n segment,\n staticChildren: null,\n paramChild: null,\n paramName: null,\n handler: null,\n paramPath: null,\n collisionNext: null,\n };\n node.staticChildren.set(segmentHash, child);\n } else {\n // FNV hash collision: walk the sibling chain for a true segment match,\n // appending a new node if this exact segment isn't chained yet\n while (child.segment !== segment) {\n if (!child.collisionNext) {\n child.collisionNext = {\n segmentHash,\n segment,\n staticChildren: null,\n paramChild: null,\n paramName: null,\n handler: null,\n paramPath: null,\n collisionNext: null,\n };\n }\n child = child.collisionNext;\n }\n }\n node = child;\n }\n\n i = segEnd;\n }\n\n // Store handler and parameter names for this specific route\n node.handler = handler;\n node.paramPath = paramNames.length > 0 ? paramNames : null;\n }\n\n /**\n * Search for a route in the radix tree - HASH-BASED\n */\n search(path: string): MatchResult | null {\n // Reused across calls: search is synchronous and the values are copied\n // into the fresh params object below before returning, so nothing escapes\n const paramValues = this.paramScratch;\n paramValues.length = 0;\n const result = this.searchNode(this.root, path, 0, paramValues);\n\n if (result) {\n // Build params object using stored parameter names from the matched route\n const params: Record<string, string> = {};\n if (result.paramPath) {\n for (let i = 0; i < result.paramPath.length; i++) {\n params[result.paramPath[i] as string] = paramValues[i] as string;\n }\n }\n return { handler: result.handler, params };\n }\n\n return null;\n }\n\n private searchNode(\n node: RadixNode,\n path: string,\n idx: number,\n paramValues: string[]\n ): RadixNode | null {\n const len = path.length;\n\n // Skip slashes\n while (idx < len && path.charCodeAt(idx) === 47) {\n idx++;\n }\n\n // End of path - return node if it has a handler\n if (idx === len) {\n return node.handler ? node : null;\n }\n\n // Try static children first (fastest) - hash-based lookup\n if (node.staticChildren) {\n // Extract current segment and compute hash (until next '/' or end)\n let segEnd = idx;\n const slashCode = 47; // '/'\n while (segEnd < len && path.charCodeAt(segEnd) !== slashCode) {\n segEnd++;\n }\n // Hash and compare in place - no substring allocation per segment\n const segmentHash = fastHashRange(path, idx, segEnd);\n\n // Direct hash lookup (O(1)), walking the collision chain if needed\n let child: RadixNode | null | undefined = node.staticChildren.get(segmentHash);\n while (child && !segmentEqualsRange(child.segment, path, idx, segEnd)) {\n child = child.collisionNext;\n }\n if (child) {\n const result = this.searchNode(child, path, segEnd, paramValues);\n if (result) {\n return result;\n }\n }\n }\n\n // Try parameter child\n if (node.paramChild) {\n // Find end of param value (next '/' or end of path)\n let end = idx;\n const slashCode = 47; // '/'\n while (end < len && path.charCodeAt(end) !== slashCode) {\n end++;\n }\n\n if (end > idx) {\n const paramValue = path.slice(idx, end);\n paramValues.push(paramValue);\n\n const result = this.searchNode(node.paramChild, path, end, paramValues);\n if (result) {\n return result;\n }\n\n // Backtrack if no match\n paramValues.pop();\n }\n }\n\n return null;\n }\n\n /**\n * Clear the tree\n */\n clear(): void {\n this.root = {\n segmentHash: 0,\n segment: '',\n staticChildren: null,\n paramChild: null,\n paramName: null,\n handler: null,\n paramPath: null,\n collisionNext: null,\n };\n }\n}\n\n/**\n * Method-specific radix tree router\n */\nexport class MethodRadixRouter {\n private trees: Map<string, RadixTree>;\n\n constructor() {\n this.trees = new Map();\n }\n\n /**\n * Add a route - OPTIMIZED\n */\n addRoute(method: string, path: string, handler: any): void {\n let tree = this.trees.get(method);\n if (!tree) {\n tree = new RadixTree();\n this.trees.set(method, tree);\n }\n tree.insert(path, handler);\n }\n\n /**\n * Find a route - OPTIMIZED\n */\n findRoute(method: string, path: string): MatchResult | null {\n const tree = this.trees.get(method);\n return tree ? tree.search(path) : null;\n }\n\n /**\n * Clear all routes\n */\n clear(): void {\n this.trees.clear();\n }\n}\n"]}
|
|
@@ -13,6 +13,9 @@ const logger = createFrameworkLogger('UnifiedRouter');
|
|
|
13
13
|
const rateLimitCore = new RateLimitCore();
|
|
14
14
|
const cacheCore = new CacheCore();
|
|
15
15
|
const validationCore = new ValidationCore();
|
|
16
|
+
// Canonical uppercase methods - lets dispatch skip toUpperCase for the
|
|
17
|
+
// interned method strings every adapter hands over
|
|
18
|
+
const UPPERCASE_METHODS = new Set(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS']);
|
|
16
19
|
// ===== Route Builder (Chainable API) =====
|
|
17
20
|
export class RouteBuilder {
|
|
18
21
|
schema;
|
|
@@ -156,15 +159,18 @@ export class UnifiedRouter {
|
|
|
156
159
|
poolManager = ObjectPoolManager.getInstance();
|
|
157
160
|
// Route storage optimized for different access patterns
|
|
158
161
|
// OPTIMIZATION: Separate maps per method for faster lookup (no string concat needed)
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
162
|
+
// Method -> path -> route. A Map (not a plain object) so the per-request
|
|
163
|
+
// lookup keyed by a non-constant method string stays a monomorphic Map.get
|
|
164
|
+
// instead of a megamorphic keyed object load.
|
|
165
|
+
staticRoutesByMethod = new Map([
|
|
166
|
+
['GET', new Map()],
|
|
167
|
+
['POST', new Map()],
|
|
168
|
+
['PUT', new Map()],
|
|
169
|
+
['DELETE', new Map()],
|
|
170
|
+
['PATCH', new Map()],
|
|
171
|
+
['HEAD', new Map()],
|
|
172
|
+
['OPTIONS', new Map()],
|
|
173
|
+
]);
|
|
168
174
|
dynamicRoutesBySegments = new Map(); // Grouped by segment count
|
|
169
175
|
fastPathRoutes = new Set(); // Routes with no middleware
|
|
170
176
|
allRoutes = []; // For iteration/inspection
|
|
@@ -247,13 +253,8 @@ export class UnifiedRouter {
|
|
|
247
253
|
* Clear all routes (useful for testing)
|
|
248
254
|
*/
|
|
249
255
|
clearAllRoutes() {
|
|
250
|
-
this.staticRoutesByMethod.
|
|
251
|
-
|
|
252
|
-
this.staticRoutesByMethod.PUT.clear();
|
|
253
|
-
this.staticRoutesByMethod.DELETE.clear();
|
|
254
|
-
this.staticRoutesByMethod.PATCH.clear();
|
|
255
|
-
this.staticRoutesByMethod.HEAD.clear();
|
|
256
|
-
this.staticRoutesByMethod.OPTIONS.clear();
|
|
256
|
+
for (const methodMap of this.staticRoutesByMethod.values())
|
|
257
|
+
methodMap.clear();
|
|
257
258
|
this.dynamicRoutesBySegments.clear();
|
|
258
259
|
this.fastPathRoutes.clear();
|
|
259
260
|
this.allRoutes = [];
|
|
@@ -297,6 +298,7 @@ export class UnifiedRouter {
|
|
|
297
298
|
const route = {
|
|
298
299
|
schema,
|
|
299
300
|
compiledPath: null, // Will be set lazily if needed
|
|
301
|
+
handler: schema.handler,
|
|
300
302
|
isFastPath,
|
|
301
303
|
executionOrder,
|
|
302
304
|
rateLimitConfig: schema.rateLimit,
|
|
@@ -306,7 +308,7 @@ export class UnifiedRouter {
|
|
|
306
308
|
};
|
|
307
309
|
// Store in appropriate structures
|
|
308
310
|
if (isStatic) {
|
|
309
|
-
const methodMap = this.staticRoutesByMethod
|
|
311
|
+
const methodMap = this.staticRoutesByMethod.get(schema.method);
|
|
310
312
|
if (methodMap) {
|
|
311
313
|
methodMap.set(schema.path, route);
|
|
312
314
|
}
|
|
@@ -444,21 +446,22 @@ export class UnifiedRouter {
|
|
|
444
446
|
*/
|
|
445
447
|
handleRequest(req, res) {
|
|
446
448
|
this.stats.requestCount++;
|
|
447
|
-
|
|
449
|
+
// Adapters hand over interned uppercase method strings - the Set probe
|
|
450
|
+
// skips a per-request toUpperCase call (and its scan) in the common case
|
|
451
|
+
const rawMethod = req.method;
|
|
452
|
+
const method = (rawMethod && UPPERCASE_METHODS.has(rawMethod) ? rawMethod : rawMethod?.toUpperCase());
|
|
448
453
|
const path = req.path;
|
|
449
454
|
// FAST PATH 1: Try static route Map lookup first (fastest possible - no string concat)
|
|
450
|
-
const methodMap = this.staticRoutesByMethod
|
|
455
|
+
const methodMap = this.staticRoutesByMethod.get(method);
|
|
451
456
|
if (methodMap) {
|
|
452
457
|
const staticRoute = methodMap.get(path);
|
|
453
458
|
if (staticRoute) {
|
|
454
|
-
//
|
|
455
|
-
|
|
456
|
-
req.params = {};
|
|
457
|
-
}
|
|
459
|
+
// (params untouched here: every adapter req initializes params, and
|
|
460
|
+
// the engine adapter materializes it lazily on first handler access)
|
|
458
461
|
// Fast-path execution (no middleware)
|
|
459
462
|
if (staticRoute.isFastPath) {
|
|
460
463
|
try {
|
|
461
|
-
const result = staticRoute.
|
|
464
|
+
const result = staticRoute.handler(req, res);
|
|
462
465
|
if (result && typeof result.then === 'function') {
|
|
463
466
|
return result
|
|
464
467
|
.then(actualResult => {
|
|
@@ -507,7 +510,7 @@ export class UnifiedRouter {
|
|
|
507
510
|
// Fast-path dynamic routes (no middleware)
|
|
508
511
|
if (route.isFastPath) {
|
|
509
512
|
try {
|
|
510
|
-
const result = route.
|
|
513
|
+
const result = route.handler(req, res);
|
|
511
514
|
if (result && typeof result.then === 'function') {
|
|
512
515
|
return result
|
|
513
516
|
.then(actualResult => {
|