433 lines
12 KiB
V
433 lines
12 KiB
V
module hono
|
||
|
||
import regex
|
||
|
||
// 预编译路由条目
|
||
pub struct PrecompiledRoute {
|
||
pub:
|
||
method string
|
||
pattern string
|
||
regex regex.RE
|
||
param_names []string
|
||
handler IHandler
|
||
complexity int // 路由复杂度分数
|
||
}
|
||
|
||
// 编译后的正则表达式缓存
|
||
pub struct FastCompiledRegex {
|
||
pub mut:
|
||
regex regex.RE
|
||
param_names []string
|
||
compiled bool
|
||
}
|
||
|
||
// 快速路由器(增强版本)
|
||
pub struct FastRouter {
|
||
pub mut:
|
||
static_routes map[string]IHandler
|
||
static_route_results map[string]ContextRouteMatch // 预分配的静态路由结果
|
||
precompiled_routes []PrecompiledRoute
|
||
lru_cache ContextLRUCache // 使用 LRU 缓存替代简单 map
|
||
regex_cache map[string]FastCompiledRegex // 正则表达式缓存
|
||
cache_enabled bool = true
|
||
sort_enabled bool = true // 是否启用路由排序
|
||
}
|
||
|
||
// 创建快速路由器
|
||
pub fn FastRouter.new() FastRouter {
|
||
return FastRouter{
|
||
static_routes: map[string]IHandler{}
|
||
static_route_results: map[string]ContextRouteMatch{}
|
||
precompiled_routes: []PrecompiledRoute{}
|
||
lru_cache: ContextLRUCache.new(1000) // 默认1000条缓存
|
||
regex_cache: map[string]FastCompiledRegex{}
|
||
}
|
||
}
|
||
|
||
// 创建带自定义缓存大小的快速路由器
|
||
pub fn FastRouter.new_with_cache_size(cache_size int) FastRouter {
|
||
return FastRouter{
|
||
static_routes: map[string]IHandler{}
|
||
static_route_results: map[string]ContextRouteMatch{}
|
||
precompiled_routes: []PrecompiledRoute{}
|
||
lru_cache: ContextLRUCache.new(cache_size)
|
||
regex_cache: map[string]FastCompiledRegex{}
|
||
}
|
||
}
|
||
|
||
// 添加路由(预编译)
|
||
pub fn (mut router FastRouter) add_route(method string, handler IHandler, base_path string) ! {
|
||
full_path := handler.path
|
||
|
||
// 静态路由直接存储,并预分配匹配结果
|
||
if !full_path.contains(':') && !full_path.contains('*') {
|
||
key := '${method}:${full_path}'
|
||
router.static_routes[key] = handler
|
||
// 预分配匹配结果,避免每次查询时创建新对象
|
||
router.static_route_results[key] = ContextRouteMatch{
|
||
handler: handler
|
||
params: map[string]string{}
|
||
path: full_path
|
||
base_path: ''
|
||
}
|
||
return
|
||
}
|
||
|
||
// 动态路由预编译
|
||
compiled_route := router.precompile_route(method, handler) or {
|
||
return error('Failed to precompile route ${full_path}: ${err}')
|
||
}
|
||
|
||
router.precompiled_routes << compiled_route
|
||
|
||
// 如果启用排序,按复杂度排序
|
||
if router.sort_enabled {
|
||
router.sort_dynamic_routes()
|
||
}
|
||
}
|
||
|
||
// 按路由复杂度排序动态路由(简单路由优先)
|
||
fn (mut router FastRouter) sort_dynamic_routes() {
|
||
router.precompiled_routes.sort_with_compare(fn (a &PrecompiledRoute, b &PrecompiledRoute) int {
|
||
if a.complexity < b.complexity {
|
||
return -1
|
||
} else if a.complexity > b.complexity {
|
||
return 1
|
||
}
|
||
return 0
|
||
})
|
||
}
|
||
|
||
// 计算路由复杂度分数(FastRouter 版本)
|
||
fn calculate_fast_route_complexity(path string) int {
|
||
mut score := 0
|
||
|
||
// 参数数量(每个参数+10分)
|
||
score += path.count(':') * 10
|
||
|
||
// 通配符(每个通配符+20分)
|
||
score += path.count('*') * 20
|
||
|
||
// 路径段数量(每个段+1分)
|
||
score += path.split('/').len
|
||
|
||
// 特殊字符(每个+5分)
|
||
special_chars := ['?', '+', '.', '(', ')', '[', ']', '{', '}', '^', '$', '|']
|
||
for ch in special_chars {
|
||
score += path.count(ch) * 5
|
||
}
|
||
|
||
return score
|
||
}
|
||
|
||
// 预编译路由
|
||
fn (router FastRouter) precompile_route(method string, handler IHandler) !PrecompiledRoute {
|
||
route_path := handler.path
|
||
|
||
// 计算路由复杂度
|
||
complexity := calculate_fast_route_complexity(route_path)
|
||
|
||
// 提取参数名
|
||
mut param_names := []string{}
|
||
mut param_reg := regex.regex_opt(r':[a-zA-Z_][a-zA-Z0-9_]*') or {
|
||
return error('Failed to create param regex')
|
||
}
|
||
|
||
all_params := param_reg.find_all_str(route_path)
|
||
for param in all_params {
|
||
param_names << param[1..] // 去掉冒号
|
||
}
|
||
|
||
// 构建正则表达式
|
||
mut regex_pattern := route_path
|
||
|
||
// 转义特殊字符
|
||
special_chars := ['?', '+', '.', '(', ')', '[', ']', '{', '}', '^', '$', '|']
|
||
for ch in special_chars {
|
||
regex_pattern = regex_pattern.replace(ch, '\\${ch}')
|
||
}
|
||
|
||
// 替换参数为命名捕获组
|
||
regex_pattern = param_reg.replace_by_fn(regex_pattern, fn (re regex.RE, in_txt string, start int, end int) string {
|
||
param_name := in_txt[start+1..end]
|
||
return '(?P<${param_name}>[^/]+)'
|
||
})
|
||
|
||
// 添加锚点
|
||
regex_pattern = '^${regex_pattern}$'
|
||
|
||
// 编译正则表达式
|
||
compiled_regex := regex.regex_opt(regex_pattern) or {
|
||
return error('Failed to compile regex: ${regex_pattern}')
|
||
}
|
||
|
||
return PrecompiledRoute{
|
||
method: method
|
||
pattern: route_path
|
||
regex: compiled_regex
|
||
param_names: param_names
|
||
handler: handler
|
||
complexity: complexity
|
||
}
|
||
}
|
||
|
||
// 快速路由匹配(优化版:静态路由跳过缓存 + 预分配结果 + 复用 cache key)
|
||
pub fn (mut router FastRouter) match_route(method string, path string) ?ContextRouteMatch {
|
||
// 优化:只拼接一次 cache key,复用于静态路由和缓存查找
|
||
cache_key := '${method}:${path}'
|
||
|
||
// 1. 静态路由直接返回预分配的结果(零分配)
|
||
if result := router.static_route_results[cache_key] {
|
||
return result
|
||
}
|
||
|
||
// 2. 动态路由先检查 LRU 缓存(避免重复正则匹配)
|
||
if router.cache_enabled {
|
||
if cached := router.lru_cache.get(cache_key) {
|
||
return cached
|
||
}
|
||
}
|
||
|
||
// 3. 预编译动态路由匹配(已按复杂度排序)
|
||
for route in router.precompiled_routes {
|
||
if route.method != method {
|
||
continue
|
||
}
|
||
|
||
if route.regex.matches_string(path) {
|
||
// 提取参数
|
||
mut params := map[string]string{}
|
||
for param_name in route.param_names {
|
||
group := route.regex.get_group_by_name(path, param_name)
|
||
params[param_name] = group
|
||
}
|
||
|
||
result := ContextRouteMatch{
|
||
handler: route.handler
|
||
params: params
|
||
path: route.pattern
|
||
base_path: ''
|
||
}
|
||
|
||
// 只缓存动态路由结果(复用 cache_key)
|
||
if router.cache_enabled {
|
||
router.lru_cache.put(cache_key, result)
|
||
}
|
||
|
||
return result
|
||
}
|
||
}
|
||
|
||
return none
|
||
}
|
||
|
||
// 获取路由统计
|
||
pub fn (router FastRouter) get_stats() (int, int, int) {
|
||
cache_size, _ := router.lru_cache.get_stats()
|
||
return router.static_routes.len, router.precompiled_routes.len, cache_size
|
||
}
|
||
|
||
// 获取详细统计信息
|
||
pub fn (mut router FastRouter) get_detailed_stats() map[string]i64 {
|
||
cache_stats := router.lru_cache.get_detailed_stats()
|
||
|
||
mut regex_compiled := 0
|
||
for _, cached_regex in router.regex_cache {
|
||
if cached_regex.compiled {
|
||
regex_compiled++
|
||
}
|
||
}
|
||
|
||
mut stats := map[string]i64{}
|
||
stats['static_routes'] = i64(router.static_routes.len)
|
||
stats['dynamic_routes'] = i64(router.precompiled_routes.len)
|
||
stats['regex_cache_total'] = i64(router.regex_cache.len)
|
||
stats['regex_cache_compiled'] = i64(regex_compiled)
|
||
stats['cache_enabled'] = if router.cache_enabled { 1 } else { 0 }
|
||
stats['sort_enabled'] = if router.sort_enabled { 1 } else { 0 }
|
||
|
||
// 合并 LRU 缓存统计
|
||
for key, value in cache_stats {
|
||
stats['lru_${key}'] = value
|
||
}
|
||
|
||
return stats
|
||
}
|
||
|
||
// 获取缓存统计信息
|
||
pub fn (router FastRouter) get_cache_stats() (int, int) {
|
||
return router.lru_cache.get_stats()
|
||
}
|
||
|
||
// 获取正则表达式缓存统计信息
|
||
pub fn (router FastRouter) get_regex_cache_stats() (int, int) {
|
||
mut compiled_count := 0
|
||
for _, cached_regex in router.regex_cache {
|
||
if cached_regex.compiled {
|
||
compiled_count++
|
||
}
|
||
}
|
||
return router.regex_cache.len, compiled_count
|
||
}
|
||
|
||
// 清理缓存
|
||
pub fn (mut router FastRouter) clear_cache() {
|
||
router.lru_cache.clear()
|
||
}
|
||
|
||
// 清理正则表达式缓存
|
||
pub fn (mut router FastRouter) clear_regex_cache() {
|
||
router.regex_cache.clear()
|
||
}
|
||
|
||
// 强制清理过期缓存
|
||
pub fn (mut router FastRouter) force_cleanup_expired() {
|
||
router.lru_cache.force_cleanup_expired()
|
||
}
|
||
|
||
// 启用/禁用缓存
|
||
pub fn (mut router FastRouter) set_cache_enabled(enabled bool) {
|
||
router.cache_enabled = enabled
|
||
if !enabled {
|
||
router.clear_cache()
|
||
}
|
||
}
|
||
|
||
// 启用/禁用路由排序
|
||
pub fn (mut router FastRouter) set_sort_enabled(enabled bool) {
|
||
router.sort_enabled = enabled
|
||
if enabled {
|
||
router.sort_dynamic_routes()
|
||
}
|
||
}
|
||
|
||
// 设置缓存 TTL
|
||
pub fn (mut router FastRouter) set_cache_ttl(ttl_seconds i64) {
|
||
router.lru_cache.set_ttl(ttl_seconds)
|
||
}
|
||
|
||
// 设置缓存清理间隔
|
||
pub fn (mut router FastRouter) set_cache_cleanup_interval(interval_seconds i64) {
|
||
router.lru_cache.set_cleanup_interval(interval_seconds)
|
||
}
|
||
|
||
// 检查路由器健康状态
|
||
pub fn (mut router FastRouter) is_healthy() bool {
|
||
return router.lru_cache.is_healthy()
|
||
}
|
||
|
||
// 预热缓存
|
||
pub fn (mut router FastRouter) warmup_cache(common_paths []string, method string) {
|
||
if !router.cache_enabled {
|
||
return
|
||
}
|
||
|
||
for path in common_paths {
|
||
router.match_route(method, path)
|
||
}
|
||
}
|
||
|
||
// 预热正则表达式缓存
|
||
pub fn (mut router FastRouter) warmup_regex_cache() {
|
||
println('[INFO] Warming up FastRouter regex cache...')
|
||
warmed_count := router.precompiled_routes.len
|
||
|
||
// 预编译的路由已经有编译好的正则表达式
|
||
// 这里可以进行一些预热操作
|
||
|
||
println('[INFO] FastRouter regex cache warmup completed: ${warmed_count} patterns ready')
|
||
}
|
||
|
||
// 智能预热(基于路由复杂度)
|
||
pub fn (mut router FastRouter) smart_warmup(sample_paths []string) {
|
||
if !router.cache_enabled {
|
||
return
|
||
}
|
||
|
||
println('[INFO] Starting smart warmup for FastRouter...')
|
||
|
||
// 按复杂度分组预热
|
||
mut simple_routes := []string{}
|
||
mut complex_routes := []string{}
|
||
|
||
for route in router.precompiled_routes {
|
||
if route.complexity <= 20 {
|
||
simple_routes << route.pattern
|
||
} else {
|
||
complex_routes << route.pattern
|
||
}
|
||
}
|
||
|
||
// 先预热简单路由
|
||
for path in sample_paths {
|
||
router.match_route('GET', path)
|
||
}
|
||
|
||
println('[INFO] Smart warmup completed: ${simple_routes.len} simple, ${complex_routes.len} complex routes')
|
||
}
|
||
|
||
// 获取所有路由
|
||
pub fn (router FastRouter) get_all_routes() ([]string, []string) {
|
||
mut static_paths := []string{}
|
||
mut dynamic_paths := []string{}
|
||
|
||
for key in router.static_routes.keys() {
|
||
static_paths << key
|
||
}
|
||
|
||
for route in router.precompiled_routes {
|
||
dynamic_paths << '${route.method}:${route.pattern} (complexity: ${route.complexity})'
|
||
}
|
||
|
||
return static_paths, dynamic_paths
|
||
}
|
||
|
||
// 获取路由按复杂度分组
|
||
pub fn (router FastRouter) get_routes_by_complexity() ([]PrecompiledRoute, []PrecompiledRoute) {
|
||
mut simple_routes := []PrecompiledRoute{}
|
||
mut complex_routes := []PrecompiledRoute{}
|
||
|
||
for route in router.precompiled_routes {
|
||
if route.complexity <= 30 {
|
||
simple_routes << route
|
||
} else {
|
||
complex_routes << route
|
||
}
|
||
}
|
||
|
||
return simple_routes, complex_routes
|
||
}
|
||
|
||
// 性能分析
|
||
pub fn (mut router FastRouter) analyze_performance() {
|
||
static_count, dynamic_count, cache_count := router.get_stats()
|
||
regex_total, regex_compiled := router.get_regex_cache_stats()
|
||
|
||
println('[ENHANCED FAST ROUTER] Performance Analysis:')
|
||
println(' Static Routes: ${static_count}')
|
||
println(' Precompiled Dynamic Routes: ${dynamic_count}')
|
||
println(' LRU Cache Size: ${cache_count}')
|
||
println(' Regex Cache: ${regex_compiled}/${regex_total} compiled')
|
||
println(' Cache Enabled: ${router.cache_enabled}')
|
||
println(' Sort Enabled: ${router.sort_enabled}')
|
||
|
||
// 显示路由复杂度分布
|
||
simple_routes, complex_routes := router.get_routes_by_complexity()
|
||
println(' Route Complexity Distribution:')
|
||
println(' Simple Routes (≤30): ${simple_routes.len}')
|
||
println(' Complex Routes (>30): ${complex_routes.len}')
|
||
|
||
// 显示缓存健康状态
|
||
if router.is_healthy() {
|
||
println(' Cache Health: ✅ Healthy')
|
||
} else {
|
||
println(' Cache Health: ⚠️ Issues detected')
|
||
}
|
||
|
||
// 显示详细统计
|
||
detailed_stats := router.get_detailed_stats()
|
||
println(' Detailed Stats:')
|
||
for key, value in detailed_stats {
|
||
println(' ${key}: ${value}')
|
||
}
|
||
} |