perf: use picoev as default Server for improve response concurrency

This commit is contained in:
meiseayoung
2025-12-30 17:31:13 +08:00
parent ee2818782b
commit a38aeea614
23 changed files with 2034 additions and 36 deletions
+83 -9
View File
@@ -1,36 +1,55 @@
# vweb vs v-hono 性能对比测试
# veb vs v-hono 性能对比测试
## 测试文件说明
| 文件 | 说明 |
|------|------|
| `benchmark_vweb_vs_hono.v` | 路由匹配性能测试(纯路由,不启动服务器) |
| `server_vweb.v` | vweb HTTP 服务器示例(端口 8080) |
| `benchmark_veb_vs_hono.v` | 路由匹配性能测试(纯路由,不启动服务器) |
| `server_veb.v` | veb HTTP 服务器示例(端口 8080)- V 语言官方新版 web 框架 |
| `server_vweb.v` | vweb HTTP 服务器示例(端口 8080)- 旧版兼容 |
| `server_hono.v` | v-hono HTTP 服务器示例(端口 8081) |
| `http_benchmark.v` | HTTP 压测工具(自动对比两个服务器) |
| `run_benchmark.ps1` | Windows PowerShell 一键测试脚本 |
## 快速开始
### Windows 用户(推荐)
```powershell
cd examples
.\run_benchmark.ps1
```
### 1. 路由匹配性能测试
```bash
v run benchmark_vweb_vs_hono.v
cd examples
v run benchmark_veb_vs_hono.v
```
### 2. HTTP 服务器压测
启动 vweb 服务器:
#### 方式一:使用内置压测工具
终端 1 - 启动 veb 服务器:
```bash
v run server_vweb.v
v run server_veb.v
```
启动 v-hono 服务器(另一个终端):
终端 2 - 启动 v-hono 服务器:
```bash
v run server_hono.v
```
使用 wrk 或 ab 进行压测:
终端 3 - 运行压测:
```bash
# 测试 vweb
v run http_benchmark.v
```
#### 方式二:使用 wrk 或 ab
```bash
# 测试 veb
wrk -t4 -c100 -d10s http://localhost:8080/
wrk -t4 -c100 -d10s http://localhost:8080/api/users/123
@@ -45,6 +64,15 @@ ab -n 10000 -c 100 http://localhost:8080/
ab -n 10000 -c 100 http://localhost:8081/
```
### 3. 编译优化版本(推荐用于正式压测)
```bash
cd examples
v -prod server_veb.v -o server_veb.exe
v -prod server_hono.v -o server_hono.exe
v -prod http_benchmark.v -o http_benchmark.exe
```
## 测试结果分析
### 路由匹配性能
@@ -71,3 +99,49 @@ ab -n 10000 -c 100 http://localhost:8081/
| `GET /api/users/:id/posts` | 动态 | 获取用户的帖子 |
| `GET /api/users/:user_id/posts/:post_id` | 动态 | 获取特定帖子 |
| `GET /api/categories/:cat/items/:item` | 动态 | 获取分类商品 |
## 测试结果分析
### 路由匹配性能
| 路由类型 | SimpleRouter (模拟 veb) | v-hono FastRouter |
|----------|-------------------------|-------------------|
| 静态路由 | ~1000 ns/op | ~9500 ns/op |
| 动态路由 | ~15000-25000 ns/op | ~9500 ns/op |
### HTTP 吞吐量(参考值)
| 端点类型 | veb | v-hono | 说明 |
|----------|-----|--------|------|
| 静态路由 | ~15000 req/s | ~12000 req/s | veb 略快 |
| 动态路由 | ~8000 req/s | ~10000 req/s | v-hono 更稳定 |
> 注:实际性能取决于硬件配置和系统负载
## 结论
- **静态路由**:veb/SimpleRouter 使用 map 直接查找,通常更快
- **动态路由**:v-hono 使用 Trie + 缓存,性能更稳定
- **v-hono 优势**:动态路由性能一致,不随路由复杂度增加而显著下降
- **veb 优势**:官方支持,与 V 语言生态集成更好
## 测试端点
| 端点 | 类型 | 说明 |
|------|------|------|
| `GET /` | 静态 | Hello World |
| `GET /api/health` | 静态 | 健康检查 |
| `GET /api/users` | 静态 | 获取用户列表 |
| `POST /api/users` | 静态 | 创建用户 |
| `GET /api/users/:id` | 动态 | 获取单个用户 |
| `GET /api/users/:id/posts` | 动态 | 获取用户的帖子 |
| `GET /api/users/:user_id/posts/:post_id` | 动态 | 获取特定帖子 |
| `GET /api/categories/:cat/items/:item` | 动态 | 获取分类商品 |
## 注意事项
1. **veb vs vweb**:veb 是 V 语言官方的新版 web 框架,替代了旧的 vweb
2. **编译优化**:正式压测时请使用 `-prod` 编译优化版本
3. **预热**:测试前建议先发送一些请求预热服务器
4. **环境隔离**:压测时关闭其他占用 CPU 的程序
+171
View File
@@ -0,0 +1,171 @@
# veb 优化分析 - v-hono 可借鉴的优化策略
## veb 核心优化策略
### 1. 使用 picoev 事件驱动模型
veb 使用 `picoev` 作为底层事件循环,这是一个高性能的事件驱动 I/O 库。
```v
// veb 使用 picoev 处理连接
mut pico := picoev.new(
port: params.port
raw_cb: ev_callback[A, X]
user_data: pico_context
timeout_secs: params.timeout_in_seconds
family: params.family
host: params.host
)!
pico.serve()
```
**v-hono 可借鉴:** 考虑使用 picoev 替代 `net.http.Server`,可以显著提升并发性能。
### 2. 预分配缓冲区
veb 预先分配了读写缓冲区,避免每次请求都分配内存:
```v
// 预分配缓冲区
pico_context.buf = unsafe { malloc_noscan(picoev.max_fds * max_read + 1) }
pico_context.incomplete_requests = []http.Request{len: picoev.max_fds}
pico_context.file_responses = []FileResponse{len: picoev.max_fds}
pico_context.string_responses = []StringResponse{len: picoev.max_fds}
```
**v-hono 可借鉴:** 使用对象池或预分配缓冲区减少 GC 压力。
### 3. 编译时路由生成
veb 使用 V 语言的编译时反射 `$for` 在编译时生成路由表:
```v
fn generate_routes[A, X](app &A) !map[string]Route {
mut routes := map[string]Route{}
$for method in A.methods {
$if method.return_type is Result {
http_methods, route_path, host := parse_attrs(method.name, method.attrs)
routes[method.name] = Route{
methods: http_methods
path: route_path
host: host
}
}
}
return routes
}
```
**v-hono 可借鉴:** 虽然 v-hono 使用运行时路由注册,但可以考虑在启动时预编译所有路由模式。
### 4. 快速响应发送
veb 使用 `strings.Builder` 构建响应,避免字符串拼接:
```v
fn fast_send_resp_header(mut conn net.TcpConn, resp http.Response) ! {
mut sb := strings.new_builder(resp.body.len + 200)
sb.write_string('HTTP/')
sb.write_string(resp.http_version)
sb.write_string(' ')
sb.write_decimal(resp.status_code)
// ...
send_string(mut conn, sb.str())!
}
```
**v-hono 可借鉴:** 使用 `strings.Builder` 替代字符串拼接构建 HTTP 响应。
### 5. 零拷贝文件传输 (sendfile)
veb 在 Linux/FreeBSD 上使用 `sendfile` 系统调用:
```v
$if linux || freebsd {
bytes_written := sendfile(fd, params.file_responses[fd].file.fd, bytes_to_write)
}
```
**v-hono 可借鉴:** 对于静态文件服务,使用 sendfile 可以避免用户态和内核态之间的数据拷贝。
### 6. 智能连接管理
veb 根据响应大小选择不同的发送策略:
```v
// 小响应直接发送
if completed_context.res.body.len < max_read {
fast_send_resp(mut conn, completed_context.res) or {}
} else {
// 大响应使用流式传输
params.string_responses[fd].open = true
params.string_responses[fd].str = completed_context.res.body
// 注册写事件
pv.add(fd, picoev.picoev_write, ...)
}
```
**v-hono 可借鉴:** 根据响应大小采用不同的发送策略。
### 7. 路由匹配优化
veb 的路由匹配策略:
1. 先匹配精确路由(不含参数)
2. 再匹配参数路由
3. 使用简单的字符串分割和比较
```v
// 精确匹配优先
if !route.path.contains('/:') && url_words == route_words {
// 直接调用处理器
app.$method(mut user_context)
return
}
// 参数路由匹配
if params := route_matches(url_words, route_words) {
app.$method(mut user_context, method_args)
return
}
```
**v-hono 可借鉴:** v-hono 已经实现了类似的静态/动态路由分离,但可以进一步优化参数提取。
### 8. 内存管理
veb 使用 `@[manualfree]` 和 `defer` 进行精细的内存管理:
```v
@[manualfree]
pub fn (mut sr StringResponse) done() {
sr.open = false
sr.pos = 0
sr.should_close_conn = false
unsafe { sr.str.free() }
}
```
**v-hono 可借鉴:** 对于频繁分配的对象,考虑手动内存管理。
## v-hono 优化建议
### 高优先级
1. **使用 picoev 替代 http.Server** - 这是最大的性能提升点
2. **预分配缓冲区** - 减少每次请求的内存分配
3. **使用 strings.Builder** - 优化响应构建
### 中优先级
4. **实现真正的 Keep-Alive** - 需要 picoev 支持
5. **优化 LRU 缓存** - 减少时间调用,使用更高效的数据结构
6. **路由预编译** - 启动时预编译所有正则表达式
### 低优先级
7. **sendfile 支持** - 静态文件零拷贝传输
8. **响应大小分级处理** - 小响应直接发送,大响应流式传输
9. **手动内存管理** - 对热点路径进行优化
## 性能对比总结
| 特性 | veb | v-hono | 差距原因 |
|------|-----|--------|----------|
| 事件模型 | picoev | http.Server | picoev 更高效 |
| Keep-Alive | ✅ 支持 | ❌ 不支持 | http.Server 限制 |
| 缓冲区 | 预分配 | 按需分配 | 内存分配开销 |
| 路由生成 | 编译时 | 运行时 | 启动时间 vs 运行时 |
| 文件传输 | sendfile | 读取+发送 | 零拷贝 vs 双拷贝 |
## 结论
v-hono 与 veb 的主要性能差距来自底层 HTTP 服务器实现。如果 v-hono 切换到 picoev,性能应该能接近甚至超过 veb。