refc: Refactor project structure
This commit is contained in:
@@ -0,0 +1,291 @@
|
||||
// vweb vs v-hono 性能对比测试
|
||||
// 测试路由匹配性能(不启动实际服务器)
|
||||
|
||||
module main
|
||||
|
||||
import time
|
||||
import hono
|
||||
import net.http
|
||||
|
||||
// ============================================
|
||||
// 测试配置
|
||||
// ============================================
|
||||
const iterations = 100_000
|
||||
const warmup_iterations = 1000
|
||||
|
||||
// ============================================
|
||||
// v-hono 路由测试
|
||||
// ============================================
|
||||
fn setup_hono_app() hono.Hono {
|
||||
mut app := hono.Hono.new()
|
||||
|
||||
// 静态路由
|
||||
app.get('/', fn (mut c hono.Context) http.Response {
|
||||
return c.text('Hello World')
|
||||
})
|
||||
app.get('/api/health', fn (mut c hono.Context) http.Response {
|
||||
return c.text('OK')
|
||||
})
|
||||
app.get('/api/users', fn (mut c hono.Context) http.Response {
|
||||
return c.json('{"users": []}')
|
||||
})
|
||||
app.post('/api/users', fn (mut c hono.Context) http.Response {
|
||||
return c.json('{"created": true}')
|
||||
})
|
||||
|
||||
// 动态路由
|
||||
app.get('/api/users/:id', fn (mut c hono.Context) http.Response {
|
||||
id := c.params['id'] or { '' }
|
||||
return c.json('{"id": "${id}"}')
|
||||
})
|
||||
app.get('/api/users/:id/posts', fn (mut c hono.Context) http.Response {
|
||||
return c.json('{"posts": []}')
|
||||
})
|
||||
app.get('/api/users/:id/posts/:post_id', fn (mut c hono.Context) http.Response {
|
||||
return c.json('{"post": {}}')
|
||||
})
|
||||
app.get('/api/categories/:cat/items/:item', fn (mut c hono.Context) http.Response {
|
||||
return c.json('{"item": {}}')
|
||||
})
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
fn benchmark_hono_routing(mut app hono.Hono) {
|
||||
println('\n========================================')
|
||||
println('v-hono 路由性能测试')
|
||||
println('========================================')
|
||||
|
||||
// 测试路径
|
||||
test_paths := [
|
||||
['GET', '/'],
|
||||
['GET', '/api/health'],
|
||||
['GET', '/api/users'],
|
||||
['POST', '/api/users'],
|
||||
['GET', '/api/users/123'],
|
||||
['GET', '/api/users/456/posts'],
|
||||
['GET', '/api/users/789/posts/101'],
|
||||
['GET', '/api/categories/electronics/items/phone'],
|
||||
]
|
||||
|
||||
// 预热
|
||||
println('预热中 (${warmup_iterations} 次)...')
|
||||
for _ in 0 .. warmup_iterations {
|
||||
for path_info in test_paths {
|
||||
method := path_info[0]
|
||||
path := path_info[1]
|
||||
app.fast_router.match_route(method, path) or { continue }
|
||||
}
|
||||
}
|
||||
|
||||
// 正式测试
|
||||
println('正式测试 (${iterations} 次)...\n')
|
||||
|
||||
mut total_time := i64(0)
|
||||
mut match_count := 0
|
||||
|
||||
for path_info in test_paths {
|
||||
method := path_info[0]
|
||||
path := path_info[1]
|
||||
|
||||
sw := time.new_stopwatch()
|
||||
for _ in 0 .. iterations {
|
||||
if _ := app.fast_router.match_route(method, path) {
|
||||
match_count++
|
||||
}
|
||||
}
|
||||
elapsed := sw.elapsed()
|
||||
total_time += elapsed.nanoseconds()
|
||||
|
||||
avg_ns := elapsed.nanoseconds() / iterations
|
||||
ops_per_sec := if avg_ns > 0 { 1_000_000_000 / avg_ns } else { 0 }
|
||||
|
||||
println(' ${method} ${path}')
|
||||
println(' 总耗时: ${elapsed}')
|
||||
println(' 平均: ${avg_ns} ns/op')
|
||||
println(' 吞吐: ${ops_per_sec} ops/sec')
|
||||
println('')
|
||||
}
|
||||
|
||||
total_ops := iterations * test_paths.len
|
||||
avg_total_ns := total_time / total_ops
|
||||
total_ops_per_sec := if avg_total_ns > 0 { 1_000_000_000 / avg_total_ns } else { 0 }
|
||||
|
||||
println('----------------------------------------')
|
||||
println('v-hono 总计:')
|
||||
println(' 总操作数: ${total_ops}')
|
||||
println(' 总耗时: ${total_time / 1_000_000} ms')
|
||||
println(' 平均: ${avg_total_ns} ns/op')
|
||||
println(' 吞吐: ${total_ops_per_sec} ops/sec')
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 简单的路由匹配模拟(模拟 vweb 的路由行为)
|
||||
// ============================================
|
||||
struct SimpleRouter {
|
||||
mut:
|
||||
routes map[string]string
|
||||
}
|
||||
|
||||
fn SimpleRouter.new() SimpleRouter {
|
||||
return SimpleRouter{
|
||||
routes: map[string]string{}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut r SimpleRouter) add(method string, path string) {
|
||||
r.routes['${method}:${path}'] = path
|
||||
}
|
||||
|
||||
fn (r SimpleRouter) match_static(method string, path string) ?string {
|
||||
key := '${method}:${path}'
|
||||
if key in r.routes {
|
||||
return r.routes[key]
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
// 模拟 vweb 的简单路由匹配(基于字符串比较)
|
||||
fn (r SimpleRouter) match_simple(method string, path string) ?string {
|
||||
// vweb 使用属性注解和函数名映射,这里模拟其基本行为
|
||||
key := '${method}:${path}'
|
||||
if key in r.routes {
|
||||
return r.routes[key]
|
||||
}
|
||||
|
||||
// 简单的动态路由匹配(模拟 vweb 的参数提取)
|
||||
for route_key, route_path in r.routes {
|
||||
if route_key.starts_with('${method}:') {
|
||||
if match_dynamic_simple(route_path, path) {
|
||||
return route_path
|
||||
}
|
||||
}
|
||||
}
|
||||
return none
|
||||
}
|
||||
|
||||
// 简单的动态路由匹配
|
||||
fn match_dynamic_simple(pattern string, path string) bool {
|
||||
pattern_parts := pattern.split('/')
|
||||
path_parts := path.split('/')
|
||||
|
||||
if pattern_parts.len != path_parts.len {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, part in pattern_parts {
|
||||
if part.starts_with(':') {
|
||||
continue // 参数匹配任意值
|
||||
}
|
||||
if part != path_parts[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fn benchmark_simple_routing() {
|
||||
println('\n========================================')
|
||||
println('简单路由器性能测试 (模拟 vweb 行为)')
|
||||
println('========================================')
|
||||
|
||||
mut router := SimpleRouter.new()
|
||||
|
||||
// 添加路由
|
||||
router.add('GET', '/')
|
||||
router.add('GET', '/api/health')
|
||||
router.add('GET', '/api/users')
|
||||
router.add('POST', '/api/users')
|
||||
router.add('GET', '/api/users/:id')
|
||||
router.add('GET', '/api/users/:id/posts')
|
||||
router.add('GET', '/api/users/:id/posts/:post_id')
|
||||
router.add('GET', '/api/categories/:cat/items/:item')
|
||||
|
||||
test_paths := [
|
||||
['GET', '/'],
|
||||
['GET', '/api/health'],
|
||||
['GET', '/api/users'],
|
||||
['POST', '/api/users'],
|
||||
['GET', '/api/users/123'],
|
||||
['GET', '/api/users/456/posts'],
|
||||
['GET', '/api/users/789/posts/101'],
|
||||
['GET', '/api/categories/electronics/items/phone'],
|
||||
]
|
||||
|
||||
// 预热
|
||||
println('预热中 (${warmup_iterations} 次)...')
|
||||
for _ in 0 .. warmup_iterations {
|
||||
for path_info in test_paths {
|
||||
method := path_info[0]
|
||||
path := path_info[1]
|
||||
router.match_simple(method, path) or { continue }
|
||||
}
|
||||
}
|
||||
|
||||
// 正式测试
|
||||
println('正式测试 (${iterations} 次)...\n')
|
||||
|
||||
mut total_time := i64(0)
|
||||
|
||||
for path_info in test_paths {
|
||||
method := path_info[0]
|
||||
path := path_info[1]
|
||||
|
||||
sw := time.new_stopwatch()
|
||||
for _ in 0 .. iterations {
|
||||
router.match_simple(method, path) or { continue }
|
||||
}
|
||||
elapsed := sw.elapsed()
|
||||
total_time += elapsed.nanoseconds()
|
||||
|
||||
avg_ns := elapsed.nanoseconds() / iterations
|
||||
ops_per_sec := if avg_ns > 0 { 1_000_000_000 / avg_ns } else { 0 }
|
||||
|
||||
println(' ${method} ${path}')
|
||||
println(' 总耗时: ${elapsed}')
|
||||
println(' 平均: ${avg_ns} ns/op')
|
||||
println(' 吞吐: ${ops_per_sec} ops/sec')
|
||||
println('')
|
||||
}
|
||||
|
||||
total_ops := iterations * test_paths.len
|
||||
avg_total_ns := total_time / total_ops
|
||||
total_ops_per_sec := if avg_total_ns > 0 { 1_000_000_000 / avg_total_ns } else { 0 }
|
||||
|
||||
println('----------------------------------------')
|
||||
println('简单路由器 总计:')
|
||||
println(' 总操作数: ${total_ops}')
|
||||
println(' 总耗时: ${total_time / 1_000_000} ms')
|
||||
println(' 平均: ${avg_total_ns} ns/op')
|
||||
println(' 吞吐: ${total_ops_per_sec} ops/sec')
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 主函数
|
||||
// ============================================
|
||||
fn main() {
|
||||
println('╔══════════════════════════════════════════════════════════════╗')
|
||||
println('║ vweb vs v-hono 路由性能对比测试 ║')
|
||||
println('╠══════════════════════════════════════════════════════════════╣')
|
||||
println('║ 测试内容: 路由匹配性能 ║')
|
||||
println('║ 迭代次数: ${iterations} ║')
|
||||
println('║ 预热次数: ${warmup_iterations} ║')
|
||||
println('╚══════════════════════════════════════════════════════════════╝')
|
||||
|
||||
// 测试简单路由器(模拟 vweb)
|
||||
benchmark_simple_routing()
|
||||
|
||||
// 测试 v-hono
|
||||
mut hono_app := setup_hono_app()
|
||||
benchmark_hono_routing(mut hono_app)
|
||||
|
||||
// 输出对比总结
|
||||
println('\n╔══════════════════════════════════════════════════════════════╗')
|
||||
println('║ 测试完成 ║')
|
||||
println('╠══════════════════════════════════════════════════════════════╣')
|
||||
println('║ 说明: ║')
|
||||
println('║ - 简单路由器模拟了 vweb 的基本路由匹配行为 ║')
|
||||
println('║ - v-hono 使用了优化的 FastRouter 和缓存机制 ║')
|
||||
println('║ - 实际 HTTP 服务器性能还受网络 I/O 等因素影响 ║')
|
||||
println('╚══════════════════════════════════════════════════════════════╝')
|
||||
}
|
||||
Reference in New Issue
Block a user