perf: use picoev as default Server for improve response concurrency
This commit is contained in:
@@ -100,7 +100,7 @@ fn main() {
|
||||
})
|
||||
|
||||
println('🚀 用户角色菜单管理系统已启动')
|
||||
println('📱 访问地址: http://localhost:3000')
|
||||
println('📱 访问地址: http://127.0.0.1:3000')
|
||||
println('')
|
||||
println('📋 示例用户:')
|
||||
println(' 用户名: admin, 密码: admin123, 角色: admin')
|
||||
|
||||
@@ -42,6 +42,6 @@ fn main() {
|
||||
return c.json('{"received": "${body}"}')
|
||||
})
|
||||
|
||||
println('Server starting on http://localhost:3000')
|
||||
println('Server starting on http://127.0.0.1:3000')
|
||||
app.listen(':3000')
|
||||
}
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
// veb vs v-hono 性能对比测试
|
||||
// 运行: v run benchmark_veb_vs_hono.v
|
||||
//
|
||||
// 测试内容:
|
||||
// 1. 路由匹配性能(纯路由,不启动服务器)
|
||||
// 2. 静态路由 vs 动态路由性能对比
|
||||
// 3. 缓存命中率分析
|
||||
|
||||
module main
|
||||
|
||||
import time
|
||||
import hono
|
||||
import net.http
|
||||
|
||||
// ============================================
|
||||
// 测试配置
|
||||
// ============================================
|
||||
const iterations = 10000
|
||||
const warmup_iterations = 1000
|
||||
|
||||
// 测试路径
|
||||
const static_paths = [
|
||||
'/',
|
||||
'/api/health',
|
||||
'/api/users',
|
||||
]
|
||||
|
||||
const dynamic_paths = [
|
||||
'/api/users/123',
|
||||
'/api/users/456/posts',
|
||||
'/api/users/789/posts/101',
|
||||
'/api/categories/electronics/items/phone',
|
||||
]
|
||||
|
||||
// ============================================
|
||||
// 简单路由器(模拟 veb 的路由匹配方式)
|
||||
// ============================================
|
||||
struct SimpleRouter {
|
||||
mut:
|
||||
static_routes map[string]string
|
||||
dynamic_routes []DynamicRoute
|
||||
}
|
||||
|
||||
struct DynamicRoute {
|
||||
pattern string
|
||||
param_names []string
|
||||
}
|
||||
|
||||
fn SimpleRouter.new() SimpleRouter {
|
||||
return SimpleRouter{
|
||||
static_routes: map[string]string{}
|
||||
dynamic_routes: []DynamicRoute{}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut r SimpleRouter) add_static(path string) {
|
||||
r.static_routes[path] = path
|
||||
}
|
||||
|
||||
fn (mut r SimpleRouter) add_dynamic(pattern string, param_names []string) {
|
||||
r.dynamic_routes << DynamicRoute{pattern, param_names}
|
||||
}
|
||||
|
||||
// 简单的动态路由匹配(模拟 veb 的线性扫描方式)
|
||||
fn (r SimpleRouter) match_route(path string) (bool, map[string]string) {
|
||||
// 1. 先尝试静态匹配
|
||||
if path in r.static_routes {
|
||||
return true, map[string]string{}
|
||||
}
|
||||
|
||||
// 2. 动态路由匹配(线性扫描)
|
||||
path_parts := path.split('/').filter(it.len > 0)
|
||||
|
||||
for route in r.dynamic_routes {
|
||||
pattern_parts := route.pattern.split('/').filter(it.len > 0)
|
||||
|
||||
if path_parts.len != pattern_parts.len {
|
||||
continue
|
||||
}
|
||||
|
||||
mut matched := true
|
||||
mut params := map[string]string{}
|
||||
mut param_idx := 0
|
||||
|
||||
for i, part in pattern_parts {
|
||||
if part.starts_with(':') {
|
||||
// 参数匹配
|
||||
if param_idx < route.param_names.len {
|
||||
params[route.param_names[param_idx]] = path_parts[i]
|
||||
param_idx++
|
||||
}
|
||||
} else if part != path_parts[i] {
|
||||
matched = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if matched {
|
||||
return true, params
|
||||
}
|
||||
}
|
||||
|
||||
return false, map[string]string{}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 基准测试函数
|
||||
// ============================================
|
||||
struct BenchmarkResult {
|
||||
name string
|
||||
total_time_ns i64
|
||||
avg_time_ns i64
|
||||
min_time_ns i64
|
||||
max_time_ns i64
|
||||
ops_per_sec f64
|
||||
iterations int
|
||||
}
|
||||
|
||||
fn benchmark(name string, iterations int, f fn () bool) BenchmarkResult {
|
||||
mut times := []i64{cap: iterations}
|
||||
mut min_time := i64(9223372036854775807)
|
||||
mut max_time := i64(0)
|
||||
|
||||
// 预热
|
||||
for _ in 0 .. warmup_iterations {
|
||||
f()
|
||||
}
|
||||
|
||||
// 正式测试
|
||||
for _ in 0 .. iterations {
|
||||
sw := time.new_stopwatch()
|
||||
f()
|
||||
elapsed := sw.elapsed().nanoseconds()
|
||||
times << elapsed
|
||||
|
||||
if elapsed < min_time {
|
||||
min_time = elapsed
|
||||
}
|
||||
if elapsed > max_time {
|
||||
max_time = elapsed
|
||||
}
|
||||
}
|
||||
|
||||
mut total := i64(0)
|
||||
for t in times {
|
||||
total += t
|
||||
}
|
||||
|
||||
avg := total / iterations
|
||||
ops_per_sec := 1_000_000_000.0 / f64(avg)
|
||||
|
||||
return BenchmarkResult{
|
||||
name: name
|
||||
total_time_ns: total
|
||||
avg_time_ns: avg
|
||||
min_time_ns: min_time
|
||||
max_time_ns: max_time
|
||||
ops_per_sec: ops_per_sec
|
||||
iterations: iterations
|
||||
}
|
||||
}
|
||||
|
||||
fn print_result(r BenchmarkResult) {
|
||||
println('┌─────────────────────────────────────────────────────────────┐')
|
||||
println('│ ${r.name:-59} │')
|
||||
println('├─────────────────────────────────────────────────────────────┤')
|
||||
println('│ 迭代次数: ${r.iterations:-48} │')
|
||||
println('│ 总耗时: ${r.total_time_ns / 1_000_000:-45} ms │')
|
||||
println('│ 平均耗时: ${r.avg_time_ns:-45} ns │')
|
||||
println('│ 最小耗时: ${r.min_time_ns:-45} ns │')
|
||||
println('│ 最大耗时: ${r.max_time_ns:-45} ns │')
|
||||
println('│ 吞吐量: ${r.ops_per_sec:-42.0} ops/s │')
|
||||
println('└─────────────────────────────────────────────────────────────┘')
|
||||
}
|
||||
|
||||
fn print_comparison(name string, simple_result BenchmarkResult, hono_result BenchmarkResult) {
|
||||
speedup := f64(simple_result.avg_time_ns) / f64(hono_result.avg_time_ns)
|
||||
winner := if speedup > 1.0 { 'v-hono' } else { 'SimpleRouter' }
|
||||
ratio := if speedup > 1.0 { speedup } else { 1.0 / speedup }
|
||||
|
||||
println('')
|
||||
println('═══════════════════════════════════════════════════════════════')
|
||||
println(' ${name} 对比结果')
|
||||
println('═══════════════════════════════════════════════════════════════')
|
||||
println(' SimpleRouter: ${simple_result.avg_time_ns} ns/op (${simple_result.ops_per_sec:.0} ops/s)')
|
||||
println(' v-hono: ${hono_result.avg_time_ns} ns/op (${hono_result.ops_per_sec:.0} ops/s)')
|
||||
println(' 胜出: ${winner} (快 ${ratio:.2}x)')
|
||||
println('═══════════════════════════════════════════════════════════════')
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 主测试函数
|
||||
// ============================================
|
||||
fn main() {
|
||||
println('')
|
||||
println('╔═══════════════════════════════════════════════════════════════╗')
|
||||
println('║ veb vs v-hono 路由性能对比测试 ║')
|
||||
println('║ (SimpleRouter 模拟 veb 的路由匹配方式) ║')
|
||||
println('╠═══════════════════════════════════════════════════════════════╣')
|
||||
println('║ 测试配置: ║')
|
||||
println('║ - 迭代次数: ${iterations:-46} ║')
|
||||
println('║ - 预热次数: ${warmup_iterations:-46} ║')
|
||||
println('╚═══════════════════════════════════════════════════════════════╝')
|
||||
println('')
|
||||
|
||||
// 初始化 SimpleRouter
|
||||
mut simple_router := SimpleRouter.new()
|
||||
simple_router.add_static('/')
|
||||
simple_router.add_static('/api/health')
|
||||
simple_router.add_static('/api/users')
|
||||
simple_router.add_dynamic('/api/users/:id', ['id'])
|
||||
simple_router.add_dynamic('/api/users/:id/posts', ['id'])
|
||||
simple_router.add_dynamic('/api/users/:user_id/posts/:post_id', ['user_id', 'post_id'])
|
||||
simple_router.add_dynamic('/api/categories/:cat/items/:item', ['cat', 'item'])
|
||||
|
||||
// 初始化 v-hono
|
||||
mut hono_app := hono.Hono.new()
|
||||
hono_app.get('/', fn (mut c hono.Context) http.Response {
|
||||
return c.text('Hello World')
|
||||
})
|
||||
hono_app.get('/api/health', fn (mut c hono.Context) http.Response {
|
||||
return c.text('OK')
|
||||
})
|
||||
hono_app.get('/api/users', fn (mut c hono.Context) http.Response {
|
||||
return c.json('{"users": []}')
|
||||
})
|
||||
hono_app.get('/api/users/:id', fn (mut c hono.Context) http.Response {
|
||||
return c.json('{"id": "123"}')
|
||||
})
|
||||
hono_app.get('/api/users/:id/posts', fn (mut c hono.Context) http.Response {
|
||||
return c.json('{"posts": []}')
|
||||
})
|
||||
hono_app.get('/api/users/:user_id/posts/:post_id', fn (mut c hono.Context) http.Response {
|
||||
return c.json('{"post": {}}')
|
||||
})
|
||||
hono_app.get('/api/categories/:cat/items/:item', fn (mut c hono.Context) http.Response {
|
||||
return c.json('{"item": {}}')
|
||||
})
|
||||
|
||||
// ============================================
|
||||
// 测试 1: 静态路由性能
|
||||
// ============================================
|
||||
println('\n【测试 1】静态路由匹配性能')
|
||||
println('─────────────────────────────────────────────────────────────────')
|
||||
|
||||
simple_static_result := benchmark('SimpleRouter 静态路由', iterations, fn [simple_router] () bool {
|
||||
for path in static_paths {
|
||||
simple_router.match_route(path)
|
||||
}
|
||||
return true
|
||||
})
|
||||
print_result(simple_static_result)
|
||||
|
||||
hono_static_result := benchmark('v-hono 静态路由', iterations, fn [mut hono_app] () bool {
|
||||
for path in static_paths {
|
||||
hono_app.fast_router.match_route('GET', path) or { continue }
|
||||
}
|
||||
return true
|
||||
})
|
||||
print_result(hono_static_result)
|
||||
|
||||
print_comparison('静态路由', simple_static_result, hono_static_result)
|
||||
|
||||
// ============================================
|
||||
// 测试 2: 动态路由性能
|
||||
// ============================================
|
||||
println('\n【测试 2】动态路由匹配性能')
|
||||
println('─────────────────────────────────────────────────────────────────')
|
||||
|
||||
simple_dynamic_result := benchmark('SimpleRouter 动态路由', iterations, fn [simple_router] () bool {
|
||||
for path in dynamic_paths {
|
||||
simple_router.match_route(path)
|
||||
}
|
||||
return true
|
||||
})
|
||||
print_result(simple_dynamic_result)
|
||||
|
||||
hono_dynamic_result := benchmark('v-hono 动态路由', iterations, fn [mut hono_app] () bool {
|
||||
for path in dynamic_paths {
|
||||
hono_app.fast_router.match_route('GET', path) or { continue }
|
||||
}
|
||||
return true
|
||||
})
|
||||
print_result(hono_dynamic_result)
|
||||
|
||||
print_comparison('动态路由', simple_dynamic_result, hono_dynamic_result)
|
||||
|
||||
// ============================================
|
||||
// 测试 3: 混合路由性能
|
||||
// ============================================
|
||||
println('\n【测试 3】混合路由匹配性能(静态 + 动态)')
|
||||
println('─────────────────────────────────────────────────────────────────')
|
||||
|
||||
mut all_paths := []string{}
|
||||
all_paths << static_paths
|
||||
all_paths << dynamic_paths
|
||||
|
||||
simple_mixed_result := benchmark('SimpleRouter 混合路由', iterations, fn [simple_router, all_paths] () bool {
|
||||
for path in all_paths {
|
||||
simple_router.match_route(path)
|
||||
}
|
||||
return true
|
||||
})
|
||||
print_result(simple_mixed_result)
|
||||
|
||||
hono_mixed_result := benchmark('v-hono 混合路由', iterations, fn [mut hono_app, all_paths] () bool {
|
||||
for path in all_paths {
|
||||
hono_app.fast_router.match_route('GET', path) or { continue }
|
||||
}
|
||||
return true
|
||||
})
|
||||
print_result(hono_mixed_result)
|
||||
|
||||
print_comparison('混合路由', simple_mixed_result, hono_mixed_result)
|
||||
|
||||
// ============================================
|
||||
// 路由器统计信息
|
||||
// ============================================
|
||||
println('\n【路由器统计信息】')
|
||||
println('─────────────────────────────────────────────────────────────────')
|
||||
|
||||
static_count, dynamic_count, cache_count, _ := hono_app.get_router_stats()
|
||||
println('v-hono FastRouter:')
|
||||
println(' - 静态路由数: ${static_count}')
|
||||
println(' - 动态路由数: ${dynamic_count}')
|
||||
println(' - 缓存条目数: ${cache_count}')
|
||||
|
||||
println('')
|
||||
println('SimpleRouter:')
|
||||
println(' - 静态路由数: ${simple_router.static_routes.len}')
|
||||
println(' - 动态路由数: ${simple_router.dynamic_routes.len}')
|
||||
|
||||
// ============================================
|
||||
// 总结
|
||||
// ============================================
|
||||
println('\n')
|
||||
println('╔═══════════════════════════════════════════════════════════════╗')
|
||||
println('║ 测试总结 ║')
|
||||
println('╠═══════════════════════════════════════════════════════════════╣')
|
||||
println('║ 1. 静态路由: SimpleRouter 使用 map 直接查找,通常更快 ║')
|
||||
println('║ 2. 动态路由: v-hono 使用 Trie + 缓存,性能更稳定 ║')
|
||||
println('║ 3. v-hono 的优势在于动态路由性能一致,不随复杂度增加而下降 ║')
|
||||
println('╚═══════════════════════════════════════════════════════════════╝')
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
// HTTP 压测工具 - veb vs v-hono 性能对比
|
||||
// 运行: v run http_benchmark.v
|
||||
//
|
||||
// 使用前请先启动服务器:
|
||||
// 终端1: v run server_veb.v (端口 8080)
|
||||
// 终端2: v run server_hono.v (端口 8081)
|
||||
|
||||
module main
|
||||
|
||||
import net.http
|
||||
import time
|
||||
|
||||
// 测试配置
|
||||
const veb_base_url = 'http://127.0.0.1:8080'
|
||||
const hono_base_url = 'http://127.0.0.1:8081'
|
||||
const requests_per_endpoint = 200
|
||||
|
||||
// 测试端点
|
||||
struct Endpoint {
|
||||
path string
|
||||
name string
|
||||
}
|
||||
|
||||
const test_endpoints = [
|
||||
Endpoint{path: '/', name: '首页 (静态)'},
|
||||
Endpoint{path: '/api/health', name: '健康检查 (静态)'},
|
||||
Endpoint{path: '/api/users', name: '用户列表 (静态)'},
|
||||
Endpoint{path: '/api/users/123', name: '单个用户 (动态)'},
|
||||
Endpoint{path: '/api/users/456/posts', name: '用户帖子 (动态)'},
|
||||
]
|
||||
|
||||
struct BenchmarkResult {
|
||||
endpoint string
|
||||
total_requests int
|
||||
success_count int
|
||||
error_count int
|
||||
total_time_ms i64
|
||||
avg_time_ms f64
|
||||
min_time_ms f64
|
||||
max_time_ms f64
|
||||
rps f64
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println('')
|
||||
println('╔═══════════════════════════════════════════════════════════════╗')
|
||||
println('║ HTTP 压测工具 - veb vs v-hono 性能对比 ║')
|
||||
println('╠═══════════════════════════════════════════════════════════════╣')
|
||||
println('║ 请确保已启动以下服务器: ║')
|
||||
println('║ - veb: v run server_veb.v (端口 8080) ║')
|
||||
println('║ - v-hono: v run server_hono.v (端口 8081) ║')
|
||||
println('╚═══════════════════════════════════════════════════════════════╝')
|
||||
println('')
|
||||
|
||||
// 检查服务器是否可用
|
||||
println('检查服务器状态...')
|
||||
veb_available := check_server(veb_base_url)
|
||||
hono_available := check_server(hono_base_url)
|
||||
|
||||
if !veb_available {
|
||||
println('⚠️ veb 服务器 (${veb_base_url}) 不可用')
|
||||
} else {
|
||||
println('✅ veb 服务器 (${veb_base_url}) 已就绪')
|
||||
}
|
||||
|
||||
if !hono_available {
|
||||
println('⚠️ v-hono 服务器 (${hono_base_url}) 不可用')
|
||||
} else {
|
||||
println('✅ v-hono 服务器 (${hono_base_url}) 已就绪')
|
||||
}
|
||||
|
||||
if !veb_available && !hono_available {
|
||||
println('')
|
||||
println('❌ 没有可用的服务器,请先启动服务器后再运行测试')
|
||||
return
|
||||
}
|
||||
|
||||
println('')
|
||||
println('开始压测 (每端点 ${requests_per_endpoint} 次请求)...')
|
||||
println('─────────────────────────────────────────────────────────────────')
|
||||
|
||||
mut veb_results := []BenchmarkResult{}
|
||||
mut hono_results := []BenchmarkResult{}
|
||||
|
||||
for endpoint in test_endpoints {
|
||||
println('')
|
||||
println('测试端点: ${endpoint.name} (${endpoint.path})')
|
||||
|
||||
if veb_available {
|
||||
result := run_benchmark('veb', veb_base_url, endpoint)
|
||||
veb_results << result
|
||||
print_single_result('veb', result)
|
||||
}
|
||||
|
||||
if hono_available {
|
||||
result := run_benchmark('v-hono', hono_base_url, endpoint)
|
||||
hono_results << result
|
||||
print_single_result('v-hono', result)
|
||||
}
|
||||
}
|
||||
|
||||
// 打印对比结果
|
||||
if veb_available && hono_available {
|
||||
print_comparison_table(veb_results, hono_results)
|
||||
}
|
||||
|
||||
// 打印总结
|
||||
print_summary(veb_results, hono_results, veb_available, hono_available)
|
||||
}
|
||||
|
||||
fn check_server(base_url string) bool {
|
||||
http.get(base_url) or { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
fn run_benchmark(name string, base_url string, endpoint Endpoint) BenchmarkResult {
|
||||
url := '${base_url}${endpoint.path}'
|
||||
|
||||
mut success_count := 0
|
||||
mut error_count := 0
|
||||
mut min_time := f64(999999.0)
|
||||
mut max_time := f64(0.0)
|
||||
mut total_req_time := f64(0.0)
|
||||
|
||||
start_time := time.now()
|
||||
|
||||
for _ in 0 .. requests_per_endpoint {
|
||||
req_start := time.now()
|
||||
|
||||
resp := http.get(url) or {
|
||||
error_count++
|
||||
continue
|
||||
}
|
||||
|
||||
req_time := f64(time.since(req_start).microseconds()) / 1000.0
|
||||
|
||||
if resp.status_code >= 200 && resp.status_code < 300 {
|
||||
success_count++
|
||||
} else {
|
||||
error_count++
|
||||
}
|
||||
|
||||
total_req_time += req_time
|
||||
if req_time < min_time {
|
||||
min_time = req_time
|
||||
}
|
||||
if req_time > max_time {
|
||||
max_time = req_time
|
||||
}
|
||||
}
|
||||
|
||||
total_time := time.since(start_time)
|
||||
total_time_ms := total_time.milliseconds()
|
||||
total_requests := success_count + error_count
|
||||
avg_time := if total_requests > 0 { total_req_time / f64(total_requests) } else { 0.0 }
|
||||
rps := if total_time_ms > 0 { f64(total_requests) * 1000.0 / f64(total_time_ms) } else { 0.0 }
|
||||
|
||||
return BenchmarkResult{
|
||||
endpoint: endpoint.name
|
||||
total_requests: total_requests
|
||||
success_count: success_count
|
||||
error_count: error_count
|
||||
total_time_ms: total_time_ms
|
||||
avg_time_ms: avg_time
|
||||
min_time_ms: min_time
|
||||
max_time_ms: max_time
|
||||
rps: rps
|
||||
}
|
||||
}
|
||||
|
||||
fn print_single_result(name string, r BenchmarkResult) {
|
||||
println(' ${name}: ${r.rps:.0} req/s | avg: ${r.avg_time_ms:.2}ms | min: ${r.min_time_ms:.2}ms | max: ${r.max_time_ms:.2}ms | 成功: ${r.success_count}/${r.total_requests}')
|
||||
}
|
||||
|
||||
fn print_comparison_table(veb_results []BenchmarkResult, hono_results []BenchmarkResult) {
|
||||
println('')
|
||||
println('╔═══════════════════════════════════════════════════════════════════════════════════════╗')
|
||||
println('║ 性能对比表 ║')
|
||||
println('╠═══════════════════════════════════════════════════════════════════════════════════════╣')
|
||||
println('║ 端点 │ veb (req/s) │ v-hono (req/s) │ 差异 │ 胜出 ║')
|
||||
println('╠═══════════════════════════════════════════════════════════════════════════════════════╣')
|
||||
|
||||
for i, veb_r in veb_results {
|
||||
if i >= hono_results.len {
|
||||
break
|
||||
}
|
||||
hono_r := hono_results[i]
|
||||
|
||||
diff := hono_r.rps - veb_r.rps
|
||||
diff_pct := if veb_r.rps > 0 { (diff / veb_r.rps) * 100.0 } else { 0.0 }
|
||||
winner := if hono_r.rps > veb_r.rps { 'v-hono' } else { 'veb' }
|
||||
|
||||
name := veb_r.endpoint
|
||||
veb_rps := '${veb_r.rps:.0}'
|
||||
hono_rps := '${hono_r.rps:.0}'
|
||||
diff_str := if diff > 0 { '+${diff_pct:.1}%' } else { '${diff_pct:.1}%' }
|
||||
|
||||
println('║ ${name:-23} │ ${veb_rps:-12} │ ${hono_rps:-14} │ ${diff_str:-9} │ ${winner:-14} ║')
|
||||
}
|
||||
|
||||
println('╚═══════════════════════════════════════════════════════════════════════════════════════╝')
|
||||
}
|
||||
|
||||
fn print_summary(veb_results []BenchmarkResult, hono_results []BenchmarkResult, veb_available bool, hono_available bool) {
|
||||
println('')
|
||||
println('╔═══════════════════════════════════════════════════════════════╗')
|
||||
println('║ 测试总结 ║')
|
||||
println('╠═══════════════════════════════════════════════════════════════╣')
|
||||
|
||||
if veb_available && veb_results.len > 0 {
|
||||
mut total_rps := f64(0.0)
|
||||
for r in veb_results {
|
||||
total_rps += r.rps
|
||||
}
|
||||
avg_rps := total_rps / f64(veb_results.len)
|
||||
println('║ veb 平均吞吐量: ${avg_rps:-40.0} req/s ║')
|
||||
}
|
||||
|
||||
if hono_available && hono_results.len > 0 {
|
||||
mut total_rps := f64(0.0)
|
||||
for r in hono_results {
|
||||
total_rps += r.rps
|
||||
}
|
||||
avg_rps := total_rps / f64(hono_results.len)
|
||||
println('║ v-hono 平均吞吐量: ${avg_rps:-40.0} req/s ║')
|
||||
}
|
||||
|
||||
println('╠═══════════════════════════════════════════════════════════════╣')
|
||||
println('║ 测试配置: ║')
|
||||
println('║ - 每端点请求数: ${requests_per_endpoint:-44} ║')
|
||||
println('╚═══════════════════════════════════════════════════════════════╝')
|
||||
|
||||
println('')
|
||||
println('提示: 使用 wrk 或 ab 可以获得更准确的压测结果:')
|
||||
println(' wrk -t4 -c100 -d10s http://127.0.0.1:8080/')
|
||||
println(' wrk -t4 -c100 -d10s http://127.0.0.1:8081/')
|
||||
}
|
||||
@@ -34,6 +34,6 @@ fn main() {
|
||||
return c.json('{"data": "some data"}')
|
||||
})
|
||||
|
||||
println('Server starting on http://localhost:3000')
|
||||
println('Server starting on http://127.0.0.1:3000')
|
||||
app.listen(':3000')
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ fn main() {
|
||||
return c.html('<h1>Desktop Version</h1>')
|
||||
})
|
||||
|
||||
println('Server running on http://localhost:8080')
|
||||
println('Server running on http://127.0.0.1:8080')
|
||||
println('Try these endpoints:')
|
||||
println(' GET /redirect-basic - Basic redirect (302)')
|
||||
println(' GET /redirect-permanent - Permanent redirect (301)')
|
||||
|
||||
@@ -31,7 +31,7 @@ fn main() {
|
||||
return c.html('<h1>Welcome to v-hono!</h1><p>API available at /api</p>')
|
||||
})
|
||||
|
||||
println('Server starting on http://localhost:3000')
|
||||
println('Server starting on http://127.0.0.1:3000')
|
||||
println('Routes:')
|
||||
println(' GET / - Welcome page')
|
||||
println(' GET /api/users - List users')
|
||||
|
||||
@@ -211,7 +211,7 @@ app.route("/api/books", mut books)</pre>
|
||||
// 打印路由信息
|
||||
fn print_routes_info() {
|
||||
println('')
|
||||
println('📍 服务器地址: http://localhost:8080')
|
||||
println('📍 服务器地址: http://127.0.0.1:8080')
|
||||
println('')
|
||||
println('📚 Books API (/api/books):')
|
||||
println(' GET /api/books - 获取所有书籍')
|
||||
|
||||
@@ -233,16 +233,16 @@ app.route(\'/api/books\', mut books)</pre>
|
||||
<div class="group">
|
||||
<h2>🧪 测试命令</h2>
|
||||
<pre># 测试 all() 方法
|
||||
curl http://localhost:8080/echo
|
||||
curl -X POST http://localhost:8080/echo
|
||||
curl -X PUT http://localhost:8080/echo
|
||||
curl http://127.0.0.1:8080/echo
|
||||
curl -X POST http://127.0.0.1:8080/echo
|
||||
curl -X PUT http://127.0.0.1:8080/echo
|
||||
|
||||
# 测试自定义 404
|
||||
curl http://localhost:8080/not-exist
|
||||
curl http://127.0.0.1:8080/not-exist
|
||||
|
||||
# 测试 Admin 认证中间件
|
||||
curl http://localhost:8080/admin # 返回 401
|
||||
curl -H "Authorization: Bearer admin-token" http://localhost:8080/admin # 成功</pre>
|
||||
curl http://127.0.0.1:8080/admin # 返回 401
|
||||
curl -H "Authorization: Bearer admin-token" http://127.0.0.1:8080/admin # 成功</pre>
|
||||
</div>
|
||||
</body>
|
||||
</html>'
|
||||
@@ -251,7 +251,7 @@ curl -H "Authorization: Bearer admin-token" http://localhost:8080/admin # 成
|
||||
// 打印路由信息
|
||||
fn print_routes_info() {
|
||||
println('')
|
||||
println('📍 服务器地址: http://localhost:8080')
|
||||
println('📍 服务器地址: http://127.0.0.1:8080')
|
||||
println('')
|
||||
println('🆕 新功能:')
|
||||
println(' - notFound(): 自定义 404 处理器')
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
# veb vs v-hono 性能对比测试脚本
|
||||
# 运行: .\run_benchmark.ps1
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "╔═══════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
|
||||
Write-Host "║ veb vs v-hono 性能对比测试 ║" -ForegroundColor Cyan
|
||||
Write-Host "╚═══════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# 检查 V 编译器
|
||||
if (-not (Get-Command v -ErrorAction SilentlyContinue)) {
|
||||
Write-Host "❌ 未找到 V 编译器,请先安装 V 语言" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "✅ V 编译器已安装" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# 菜单
|
||||
Write-Host "请选择测试类型:" -ForegroundColor Yellow
|
||||
Write-Host " 1. 路由匹配性能测试 (不需要启动服务器)"
|
||||
Write-Host " 2. HTTP 压测 (需要先启动服务器)"
|
||||
Write-Host " 3. 启动 veb 服务器 (端口 8080)"
|
||||
Write-Host " 4. 启动 v-hono 服务器 (端口 8081)"
|
||||
Write-Host " 5. 编译所有测试文件"
|
||||
Write-Host " 6. 退出"
|
||||
Write-Host ""
|
||||
|
||||
$choice = Read-Host "请输入选项 (1-6)"
|
||||
|
||||
switch ($choice) {
|
||||
"1" {
|
||||
Write-Host ""
|
||||
Write-Host "运行路由匹配性能测试..." -ForegroundColor Cyan
|
||||
v run benchmark_veb_vs_hono.v
|
||||
}
|
||||
"2" {
|
||||
Write-Host ""
|
||||
Write-Host "运行 HTTP 压测..." -ForegroundColor Cyan
|
||||
Write-Host "请确保已在其他终端启动服务器:" -ForegroundColor Yellow
|
||||
Write-Host " - veb: v run server_veb.v (端口 8080)"
|
||||
Write-Host " - v-hono: v run server_hono.v (端口 8081)"
|
||||
Write-Host ""
|
||||
v run http_benchmark.v
|
||||
}
|
||||
"3" {
|
||||
Write-Host ""
|
||||
Write-Host "启动 veb 服务器 (端口 8080)..." -ForegroundColor Cyan
|
||||
v run server_veb.v
|
||||
}
|
||||
"4" {
|
||||
Write-Host ""
|
||||
Write-Host "启动 v-hono 服务器 (端口 8081)..." -ForegroundColor Cyan
|
||||
v run server_hono.v
|
||||
}
|
||||
"5" {
|
||||
Write-Host ""
|
||||
Write-Host "编译所有测试文件..." -ForegroundColor Cyan
|
||||
|
||||
Write-Host "编译 benchmark_veb_vs_hono.v..."
|
||||
v -prod benchmark_veb_vs_hono.v -o benchmark_veb_vs_hono.exe
|
||||
|
||||
Write-Host "编译 server_veb.v..."
|
||||
v -prod server_veb.v -o server_veb.exe
|
||||
|
||||
Write-Host "编译 server_hono.v..."
|
||||
v -prod server_hono.v -o server_hono.exe
|
||||
|
||||
Write-Host "编译 http_benchmark.v..."
|
||||
v -prod http_benchmark.v -o http_benchmark.exe
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "✅ 编译完成!" -ForegroundColor Green
|
||||
}
|
||||
"6" {
|
||||
Write-Host "退出" -ForegroundColor Yellow
|
||||
exit 0
|
||||
}
|
||||
default {
|
||||
Write-Host "无效选项" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// v-hono 服务器示例 - 用于性能对比测试
|
||||
// 运行: v run server_hono.v
|
||||
// 测试: curl http://localhost:8081/
|
||||
// 测试: curl http://127.0.0.1:8081/
|
||||
|
||||
module main
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// v-hono picoev 服务器示例 - 高性能版本
|
||||
// 运行: v run server_hono_picoev.v
|
||||
// 测试: curl http://127.0.0.1:8081/
|
||||
|
||||
module main
|
||||
|
||||
import hono
|
||||
import net.http
|
||||
|
||||
fn main() {
|
||||
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 {
|
||||
id := c.params['id'] or { '' }
|
||||
return c.json('{"posts": [], "user_id": "${id}"}')
|
||||
})
|
||||
|
||||
app.get('/api/users/:user_id/posts/:post_id', fn (mut c hono.Context) http.Response {
|
||||
user_id := c.params['user_id'] or { '' }
|
||||
post_id := c.params['post_id'] or { '' }
|
||||
return c.json('{"user_id": "${user_id}", "post_id": "${post_id}"}')
|
||||
})
|
||||
|
||||
app.get('/api/categories/:cat/items/:item', fn (mut c hono.Context) http.Response {
|
||||
cat := c.params['cat'] or { '' }
|
||||
item := c.params['item'] or { '' }
|
||||
return c.json('{"category": "${cat}", "item": "${item}"}')
|
||||
})
|
||||
|
||||
println('╔═══════════════════════════════════════════════════════════════╗')
|
||||
println('║ v-hono picoev 服务器 - 高性能版本 ║')
|
||||
println('╠═══════════════════════════════════════════════════════════════╣')
|
||||
println('║ 端口: 8081 ║')
|
||||
println('║ 特性: picoev 事件驱动 + Keep-Alive ║')
|
||||
println('╚═══════════════════════════════════════════════════════════════╝')
|
||||
|
||||
// 使用 picoev 启动服务器
|
||||
app.listen_picoev(8081)
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
// veb 服务器示例 - 用于性能对比测试
|
||||
// veb 是 V 语言官方的新版 web 框架(替代旧的 vweb)
|
||||
//
|
||||
// 运行: v run server_veb.v
|
||||
// 测试: curl http://127.0.0.1:8080/
|
||||
//
|
||||
// 压测命令:
|
||||
// wrk -t4 -c100 -d10s http://127.0.0.1:8080/
|
||||
// wrk -t4 -c100 -d10s http://127.0.0.1:8080/api/users/123
|
||||
|
||||
module main
|
||||
|
||||
import veb
|
||||
import time
|
||||
|
||||
// 应用状态
|
||||
pub struct App {
|
||||
pub:
|
||||
start_time time.Time = time.now()
|
||||
}
|
||||
|
||||
// Context 类型
|
||||
pub struct Context {
|
||||
veb.Context
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println('╔═══════════════════════════════════════════════════════════════╗')
|
||||
println('║ veb 服务器 - 性能对比测试 ║')
|
||||
println('╠═══════════════════════════════════════════════════════════════╣')
|
||||
println('║ 端口: 8080 ║')
|
||||
println('║ 测试端点: ║')
|
||||
println('║ GET / - Hello World ║')
|
||||
println('║ GET /api/health - 健康检查 ║')
|
||||
println('║ GET /api/users - 获取用户列表 ║')
|
||||
println('║ POST /api/users - 创建用户 ║')
|
||||
println('║ GET /api/users/:id - 获取单个用户 ║')
|
||||
println('║ GET /api/users/:id/posts - 获取用户帖子 ║')
|
||||
println('╚═══════════════════════════════════════════════════════════════╝')
|
||||
println('')
|
||||
println('启动 veb 服务器在端口 8080...')
|
||||
|
||||
mut app := &App{}
|
||||
veb.run[App, Context](mut app, 8080)
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 静态路由
|
||||
// ============================================
|
||||
|
||||
// 首页
|
||||
@['/']
|
||||
pub fn (app &App) index(mut ctx Context) veb.Result {
|
||||
ctx.set_header(.connection, 'close')
|
||||
return ctx.text('Hello World')
|
||||
}
|
||||
|
||||
// 健康检查
|
||||
@['/api/health']
|
||||
pub fn (app &App) health(mut ctx Context) veb.Result {
|
||||
ctx.set_header(.connection, 'close')
|
||||
return ctx.text('OK')
|
||||
}
|
||||
|
||||
// 获取用户列表
|
||||
@['/api/users'; get]
|
||||
pub fn (app &App) get_users(mut ctx Context) veb.Result {
|
||||
ctx.set_header(.connection, 'close')
|
||||
return ctx.json[[]User]([
|
||||
User{id: '1', name: 'Alice', email: 'alice@example.com'},
|
||||
User{id: '2', name: 'Bob', email: 'bob@example.com'},
|
||||
])
|
||||
}
|
||||
|
||||
// 创建用户
|
||||
@['/api/users'; post]
|
||||
pub fn (app &App) create_user(mut ctx Context) veb.Result {
|
||||
ctx.set_header(.connection, 'close')
|
||||
return ctx.json[CreateResponse](CreateResponse{created: true, id: '3'})
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 动态路由
|
||||
// ============================================
|
||||
|
||||
// 获取单个用户
|
||||
@['/api/users/:id']
|
||||
pub fn (app &App) get_user(mut ctx Context, id string) veb.Result {
|
||||
ctx.set_header(.connection, 'close')
|
||||
return ctx.json[User](User{id: id, name: 'User ${id}', email: 'user${id}@example.com'})
|
||||
}
|
||||
|
||||
// 获取用户的帖子
|
||||
@['/api/users/:id/posts']
|
||||
pub fn (app &App) get_user_posts(mut ctx Context, id string) veb.Result {
|
||||
ctx.set_header(.connection, 'close')
|
||||
return ctx.json[PostsResponse](PostsResponse{
|
||||
user_id: id
|
||||
posts: [
|
||||
Post{id: '1', title: 'First Post', content: 'Hello World'},
|
||||
Post{id: '2', title: 'Second Post', content: 'V is awesome'},
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
// 获取特定帖子
|
||||
@['/api/users/:user_id/posts/:post_id']
|
||||
pub fn (app &App) get_user_post(mut ctx Context, user_id string, post_id string) veb.Result {
|
||||
ctx.set_header(.connection, 'close')
|
||||
return ctx.json[PostResponse](PostResponse{
|
||||
user_id: user_id
|
||||
post_id: post_id
|
||||
post: Post{id: post_id, title: 'Post ${post_id}', content: 'Content of post ${post_id}'}
|
||||
})
|
||||
}
|
||||
|
||||
// 获取分类商品
|
||||
@['/api/categories/:cat/items/:item']
|
||||
pub fn (app &App) get_category_item(mut ctx Context, cat string, item string) veb.Result {
|
||||
ctx.set_header(.connection, 'close')
|
||||
return ctx.json[ItemResponse](ItemResponse{
|
||||
category: cat
|
||||
item: item
|
||||
price: 99.99
|
||||
})
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 数据结构
|
||||
// ============================================
|
||||
|
||||
struct User {
|
||||
id string
|
||||
name string
|
||||
email string
|
||||
}
|
||||
|
||||
struct Post {
|
||||
id string
|
||||
title string
|
||||
content string
|
||||
}
|
||||
|
||||
struct CreateResponse {
|
||||
created bool
|
||||
id string
|
||||
}
|
||||
|
||||
struct PostsResponse {
|
||||
user_id string
|
||||
posts []Post
|
||||
}
|
||||
|
||||
struct PostResponse {
|
||||
user_id string
|
||||
post_id string
|
||||
post Post
|
||||
}
|
||||
|
||||
struct ItemResponse {
|
||||
category string
|
||||
item string
|
||||
price f64
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// vweb 服务器示例 - 用于性能对比测试
|
||||
// 运行: v run server_vweb.v
|
||||
// 测试: curl http://localhost:8080/
|
||||
// 测试: curl http://127.0.0.1:8080/
|
||||
|
||||
module main
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// 简单 HTTP 压测 - veb vs v-hono
|
||||
// v run simple_benchmark.v
|
||||
|
||||
module main
|
||||
|
||||
import net.http
|
||||
import time
|
||||
|
||||
const requests = 50
|
||||
|
||||
fn main() {
|
||||
println('╔═══════════════════════════════════════════════════════════════╗')
|
||||
println('║ 简单 HTTP 压测 - veb vs v-hono ║')
|
||||
println('╚═══════════════════════════════════════════════════════════════╝')
|
||||
println('')
|
||||
|
||||
// 测试 veb
|
||||
println('测试 veb (http://127.0.0.1:8080/)...')
|
||||
veb_result := benchmark_server('http://127.0.0.1:8080/')
|
||||
println(' 结果: ${veb_result.rps:.0} req/s | avg: ${veb_result.avg_ms:.2}ms | 成功: ${veb_result.success}/${veb_result.total}')
|
||||
|
||||
// 测试 v-hono
|
||||
println('')
|
||||
println('测试 v-hono (http://127.0.0.1:8081/)...')
|
||||
hono_result := benchmark_server('http://127.0.0.1:8081/')
|
||||
println(' 结果: ${hono_result.rps:.0} req/s | avg: ${hono_result.avg_ms:.2}ms | 成功: ${hono_result.success}/${hono_result.total}')
|
||||
|
||||
// 对比
|
||||
println('')
|
||||
println('═══════════════════════════════════════════════════════════════')
|
||||
if veb_result.rps > 0 && hono_result.rps > 0 {
|
||||
if hono_result.rps > veb_result.rps {
|
||||
ratio := hono_result.rps / veb_result.rps
|
||||
println('v-hono 快 ${ratio:.2}x')
|
||||
} else {
|
||||
ratio := veb_result.rps / hono_result.rps
|
||||
println('veb 快 ${ratio:.2}x')
|
||||
}
|
||||
}
|
||||
println('═══════════════════════════════════════════════════════════════')
|
||||
}
|
||||
|
||||
struct Result {
|
||||
total int
|
||||
success int
|
||||
rps f64
|
||||
avg_ms f64
|
||||
}
|
||||
|
||||
fn benchmark_server(url string) Result {
|
||||
// 先检查服务器
|
||||
http.get(url) or {
|
||||
println(' ⚠️ 服务器不可用')
|
||||
return Result{}
|
||||
}
|
||||
|
||||
mut success := 0
|
||||
mut total_ms := f64(0)
|
||||
|
||||
start := time.now()
|
||||
|
||||
for i in 0 .. requests {
|
||||
req_start := time.now()
|
||||
resp := http.get(url) or {
|
||||
continue
|
||||
}
|
||||
req_ms := f64(time.since(req_start).microseconds()) / 1000.0
|
||||
|
||||
if resp.status_code == 200 {
|
||||
success++
|
||||
}
|
||||
total_ms += req_ms
|
||||
|
||||
// 进度
|
||||
if (i + 1) % 10 == 0 {
|
||||
print('.')
|
||||
}
|
||||
}
|
||||
println('')
|
||||
|
||||
elapsed := time.since(start)
|
||||
elapsed_ms := elapsed.milliseconds()
|
||||
|
||||
rps := if elapsed_ms > 0 { f64(requests) * 1000.0 / f64(elapsed_ms) } else { 0.0 }
|
||||
avg_ms := if requests > 0 { total_ms / f64(requests) } else { 0.0 }
|
||||
|
||||
return Result{
|
||||
total: requests
|
||||
success: success
|
||||
rps: rps
|
||||
avg_ms: avg_ms
|
||||
}
|
||||
}
|
||||
+12
-12
@@ -21,7 +21,7 @@ fn main() {
|
||||
|
||||
// 等待服务器启动
|
||||
time.sleep(2 * time.second)
|
||||
println('服务器已启动在 http://localhost:8081')
|
||||
println('服务器已启动在 http://127.0.0.1:8081')
|
||||
|
||||
// 执行测试
|
||||
run_tests()
|
||||
@@ -124,7 +124,7 @@ fn test_small_file_performance() {
|
||||
// 传统方式
|
||||
start := time.now()
|
||||
for i in 0 .. 100 {
|
||||
_ = os.execute('curl -s http://localhost:8081/traditional/test_small.txt > nul')
|
||||
_ = os.execute('curl -s http://127.0.0.1:8081/traditional/test_small.txt > nul')
|
||||
}
|
||||
traditional_time := time.now() - start
|
||||
println('传统方式 100次请求: $traditional_time')
|
||||
@@ -132,7 +132,7 @@ fn test_small_file_performance() {
|
||||
// 流式方式
|
||||
start2 := time.now()
|
||||
for i in 0 .. 100 {
|
||||
_ = os.execute('curl -s http://localhost:8081/stream/test_small.txt > nul')
|
||||
_ = os.execute('curl -s http://127.0.0.1:8081/stream/test_small.txt > nul')
|
||||
}
|
||||
stream_time := time.now() - start2
|
||||
println('流式方式 100次请求: $stream_time')
|
||||
@@ -140,7 +140,7 @@ fn test_small_file_performance() {
|
||||
// 智能方式
|
||||
start3 := time.now()
|
||||
for i in 0 .. 100 {
|
||||
_ = os.execute('curl -s http://localhost:8081/smart/test_small.txt > nul')
|
||||
_ = os.execute('curl -s http://127.0.0.1:8081/smart/test_small.txt > nul')
|
||||
}
|
||||
smart_time := time.now() - start3
|
||||
println('智能方式 100次请求: $smart_time')
|
||||
@@ -152,7 +152,7 @@ fn test_medium_file_performance() {
|
||||
// 传统方式
|
||||
start := time.now()
|
||||
for i in 0 .. 10 {
|
||||
_ = os.execute('curl -s http://localhost:8081/traditional/test_medium.txt > nul')
|
||||
_ = os.execute('curl -s http://127.0.0.1:8081/traditional/test_medium.txt > nul')
|
||||
}
|
||||
traditional_time := time.now() - start
|
||||
println('传统方式 10次请求: $traditional_time')
|
||||
@@ -160,7 +160,7 @@ fn test_medium_file_performance() {
|
||||
// 流式方式
|
||||
start2 := time.now()
|
||||
for i in 0 .. 10 {
|
||||
_ = os.execute('curl -s http://localhost:8081/stream/test_medium.txt > nul')
|
||||
_ = os.execute('curl -s http://127.0.0.1:8081/stream/test_medium.txt > nul')
|
||||
}
|
||||
stream_time := time.now() - start2
|
||||
println('流式方式 10次请求: $stream_time')
|
||||
@@ -172,7 +172,7 @@ fn test_large_file_performance() {
|
||||
// 只测试流式方式,避免内存问题
|
||||
start := time.now()
|
||||
for i in 0 .. 5 {
|
||||
result := os.execute('curl -s http://localhost:8081/stream/test_large.txt > nul')
|
||||
result := os.execute('curl -s http://127.0.0.1:8081/stream/test_large.txt > nul')
|
||||
if result.exit_code != 0 {
|
||||
println(' 请求 $i 失败')
|
||||
}
|
||||
@@ -183,7 +183,7 @@ fn test_large_file_performance() {
|
||||
// 智能方式(应该自动选择流式传输)
|
||||
start2 := time.now()
|
||||
for i in 0 .. 5 {
|
||||
result := os.execute('curl -s http://localhost:8081/smart/test_large.txt > nul')
|
||||
result := os.execute('curl -s http://127.0.0.1:8081/smart/test_large.txt > nul')
|
||||
if result.exit_code != 0 {
|
||||
println(' 智能方式请求 $i 失败')
|
||||
}
|
||||
@@ -196,14 +196,14 @@ fn test_range_requests() {
|
||||
println('\n--- Range请求测试 ---')
|
||||
|
||||
// 测试部分内容请求
|
||||
result1 := os.execute('curl -s -H "Range: bytes=0-99" http://localhost:8081/range/test_medium.txt')
|
||||
result1 := os.execute('curl -s -H "Range: bytes=0-99" http://127.0.0.1:8081/range/test_medium.txt')
|
||||
if result1.exit_code == 0 {
|
||||
println('✅ Range请求 0-99: 成功')
|
||||
} else {
|
||||
println('❌ Range请求 0-99: 失败')
|
||||
}
|
||||
|
||||
result2 := os.execute('curl -s -H "Range: bytes=100-199" http://localhost:8081/range/test_medium.txt')
|
||||
result2 := os.execute('curl -s -H "Range: bytes=100-199" http://127.0.0.1:8081/range/test_medium.txt')
|
||||
if result2.exit_code == 0 {
|
||||
println('✅ Range请求 100-199: 成功')
|
||||
} else {
|
||||
@@ -215,7 +215,7 @@ fn test_smart_selection() {
|
||||
println('\n--- 智能选择测试 ---')
|
||||
|
||||
// 测试小文件(应该使用内存加载)
|
||||
result1 := os.execute('curl -s http://localhost:8081/smart/test_small.txt')
|
||||
result1 := os.execute('curl -s http://127.0.0.1:8081/smart/test_small.txt')
|
||||
if result1.exit_code == 0 {
|
||||
println('✅ 智能选择小文件: 成功')
|
||||
} else {
|
||||
@@ -223,7 +223,7 @@ fn test_smart_selection() {
|
||||
}
|
||||
|
||||
// 测试大文件(应该使用流式传输)
|
||||
result2 := os.execute('curl -s -o large_output.txt http://localhost:8081/smart/test_large.txt')
|
||||
result2 := os.execute('curl -s -o large_output.txt http://127.0.0.1:8081/smart/test_large.txt')
|
||||
if result2.exit_code == 0 {
|
||||
// 检查下载的文件大小
|
||||
if os.exists('large_output.txt') {
|
||||
|
||||
Reference in New Issue
Block a user