Files
Cyrene/docs/debug_log/2026-05-20-round6-performance-code-quality.md
T
AskaEth b123a36aae fix: 第四轮调试 — 回复去重/消息时序/UI布局/自主思考深度优化 + 文档重整
后端修复:
- main.go: 恢复 /api/v1/chat 路由中丢失的 handleChat 调用 (空响应回归)
- orchestrator.go: splitChatByLines 改为双换行分割, 避免单换行误拆
- chat_handler.go: multi_message 增加 !hasReview 守卫, 消息延迟 200→800ms
- thinker.go: RecordUserMessage 追踪活跃会话ID, 推送主动消息到正确会话
- thinker.go: 增强思考提示词 — 禁止在用户休息/离开时发送主动消息

前端修复:
- useWebSocket.ts: stream_segments 不再创建消息气泡, 消除重复回复
- MessageBubble.tsx: 动作消息居左对齐无头像, 时间戳移至气泡外侧 hover 显示
- ChatInput.tsx: 昔涟输入提示移至输入框上方, 波点动画效果
- MessageList/TypingIndicator/ChatContainer: 清理冗余 isTyping 传递
- MemoryPanel.tsx: 新增记忆面板组件

文档重整:
- docs/debug/ → docs/debug_log/ 重命名统一
- 新增 debug_log/README.md 索引
- .gitignore: 新增 android/ 排除规则

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 13:09:18 +08:00

301 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 第6轮调试报告:性能基准测试 + 代码质量审计
> **日期**2026-05-20 14:55 ~ 15:00 CST
> **执行模式**:🪲 Debug
> **范围**:所有6个微服务 (gateway, ai-core, iot-debug-service, memory-service, tool-engine, voice-service) + 前端
---
## 一、测试前状态检查
| 项目 | 状态 |
|------|------|
| 当前时间 | 2026-05-20 14:55:33 CST |
| 所有6个服务健康检查 | ✅ 全部 200 OK |
| 运行进程 | 6 个 Go 进程 (4× `./main` + `gateway` + `tool-engine`) |
---
## 二、性能基准测试
### 2.1 响应时间基准 (各服务 /api/v1/health, 10次采样)
| 服务 | 端口 | 平均延迟 | P50 | P95 | 最小 | 最大 |
|------|------|----------|-----|-----|------|------|
| Gateway | 8080 | **0.51ms** | 0.45ms | 0.64ms | 0.39ms | 0.94ms |
| AI-Core | 8081 | **0.76ms** | 0.39ms | 3.80ms | 0.33ms | 3.80ms |
| IoT-Debug | 8083 | **0.75ms** | 0.41ms | 3.45ms | 0.36ms | 3.45ms |
| Memory-Service | 8091 | **0.69ms** | 0.33ms | 3.00ms | 0.30ms | 3.00ms |
| Tool-Engine | 8092 | **0.81ms** | 0.35ms | 4.36ms | 0.25ms | 4.36ms |
| Voice-Service | 8093 | **1.32ms** | 0.51ms | 6.89ms | 0.34ms | 6.89ms |
> **分析**:所有服务的健康检查端点响应时间均 < 7msGateway 表现最优 (~0.5ms)。Voice-Service 首请求稍慢(冷启动/包加载),但后续稳定在 0.3-0.8ms。P95 尖峰可能来自 GC 或 OS 调度。
### 2.2 网关端点响应时间 (各5次)
| 端点 | 平均延迟 | HTTP 状态 | 备注 |
|------|----------|-----------|------|
| `/api/v1/health` | **0.68ms** | 200 | 健康检查 |
| `/api/v1/auth/login` | **0.41ms** | 404 | 无请求体 (预期 404) |
| `/api/v1/auth/register` | **0.46ms** | 404 | 无请求体 (预期 404) |
> **分析**:路由匹配开销极低 (< 1ms),Gin 框架性能优秀。
### 2.3 并发压测 (Gateway /api/v1/health)
| 并发数 | 总耗时 | 每请求平均 |
|--------|--------|------------|
| 10 | 19.68ms | 1.97ms |
| 20 | 26.92ms | 1.35ms |
| 50 | 53.48ms | 1.07ms |
> **分析**Gateway 在 50 并发下表现优异,总耗时仅 53ms。随着并发增加,平均每请求耗时反而下降(连接复用效应)。未见阻塞或排队现象。
### 2.4 内存使用
| 服务 | 进程 | RSS | VSZ | 文件描述符数 |
|------|------|-----|-----|-------------|
| Gateway | `./cmd/gateway` (PID 19265) | 12 MB | 2108 MB | 37 |
| Tool-Engine | `tool-engine` (PID 29391) | 4 MB | 1814 MB | 34 |
| AI-Core | `./main` (PID 15037) | 10 MB | 2033 MB | - |
| IoT-Debug | `./main` (PID 7641) | 4 MB | 1741 MB | - |
| Voice-Service | `./main` (PID 3063) | 4 MB | 1596 MB | - |
| Memory-Service | `./main` (PID 2434) | 4 MB | 2087 MB | - |
| 系统资源 | 值 |
|----------|-----|
| 总内存 | 14 GB |
| 已用 | 13 GB |
| 可用 | 540 MB |
| Swap 已用 | 8 GB |
> **分析**:各服务内存占用极低 (4-12 MB RSS),Go 运行时 VSZ 较大是正常的(包含预留地址空间)。**系统整体内存压力较高** (仅 540MB 可用, 8GB Swap 占用),可能是宿主机上其他进程导致,Cyrene 服务本身资源占用可忽略不计。
### 2.5 数据库连接池配置
| 服务 | MaxOpenConns | MaxIdleConns | ConnMaxLifetime | 文件 |
|------|-------------|-------------|-----------------|------|
| Gateway | 25 | 5 | 5 min | [`session_store.go`](backend/gateway/internal/store/session_store.go:45) |
| AI-Core | 25 | 5 | 5 min | [`store.go`](backend/ai-core/internal/memory/store.go:112) |
| Memory-Service | 25 | 5 | 5 min | [`store.go`](backend/memory-service/internal/store/store.go:106) |
| Tool-Engine | **5** | 2 | 5 min | [`call_log_store.go`](backend/tool-engine/internal/store/call_log_store.go:81) |
> **分析**
> - Gateway/AI-Core/Memory-Service 使用 25 连接上限,合理。
> - **Tool-Engine 仅配置 5 个连接**,如果是独立的数据库连接(非共享 PostgreSQL),合理;如果共享同一个 PG 实例,偏低但不阻塞。
> - 所有服务使用统一的 5 分钟连接生命周期,合理。
> - **缺失项**:未设置 `SetConnMaxIdleTime`Go 1.15+ 可用),空闲连接可能存在泄漏风险。
### 2.6 WebSocket 连接
| 测试 | 结果 |
|------|------|
| `/api/v1/ws` (不存在的路径) | HTTP 404 ✅ |
| `/ws/chat?token=test` | HTTP 401 (需要有效的 JWT token) ✅ |
| WebSocket 路由注册 | `/ws/chat` → [`chat_handler.go`](backend/gateway/internal/handler/chat_handler.go:46) |
> **分析**WebSocket 路由正确注册在 `/ws/chat`,需要 Bearer token 认证。Connection upgrade 行为正确。建立连接的延迟依赖 JWT 验证速度 (<1ms)。
---
## 三、Go 代码质量审计
### 3.1 错误处理与 HTTP 状态码一致性
| 检查项 | 结果 |
|--------|------|
| HTTP 状态码使用 | ✅ 非常一致,正确使用 200/201/400/401/403/404/409/422/429/500/502/503 |
| 错误响应格式 | ✅ 统一使用 `{"error": "..."}` / `gin.H{"error": "..."}` |
| 错误信息中文 | ✅ 全部中文错误提示 |
| errorType 标注 | ✅ gateway handler 普遍使用 `errorType` 字段进行细粒度分类 |
> **亮点**:所有 gateway handler 的 HTTP 状态码映射非常精确,如 `StatusConflict`(409) 用于用户名已注册,`StatusBadGateway`(502) 用于后端服务不可达,`StatusForbidden`(403) 用于权限不足。
### 3.2 日志级别检查
| 检查项 | 结果 |
|--------|------|
| `fmt.Println/Printf` | ✅ **0 处** — 无生产代码使用 |
| `log.Printf` | ✅ 全部使用 `log.Printf`,带模块前缀如 `[memory]``[ws]``[subsession]` |
| 关键操作日志 | ✅ 数据库初始化、服务启动、连接建立/断开均有日志 |
> **分析**:日志规范执行到位,无 `fmt.Println` 污染 stdout,所有日志使用 `log` 包且带上下文标签。
### 3.3 Panic 恢复
| 检查项 | 结果 |
|--------|------|
| 主动 `panic()` | ✅ **0 处** — 无业务代码 panic |
| `recover()` 保护 | ✅ **9 处**,覆盖所有 goroutine 入口 |
| 受保护的 goroutine | 后台思考(3)、子会话分发(2)、编排器(1)、WebSocket 清理(2)、提醒调度器(1) |
> **分析**:所有长时间运行的 goroutine 均有 `defer recover()` 保护,防止单个 goroutine panic 导致整个进程崩溃。这是 Go 并发编程的最佳实践。
### 3.4 硬编码值审计
| 类型 | 位置 | 默认值 | 风险等级 |
|------|------|--------|----------|
| 数据库密码 | 3 处 config | `"change_me"` | 🟡 低 (通过环境变量覆盖) |
| 管理员密码 | [`config.go:97`](backend/gateway/internal/config/config.go:97) | `"cyrene-dev-admin"` | 🟡 低 |
| 内部服务 Token | [`config.go:121`](backend/gateway/internal/config/config.go:121) | `"cyrene-internal-token-change-me"` | 🟠 中 (建议改为随机生成) |
| 服务间 URL | 6 处 config | `localhost:808x/809x` | 🟢 信息 (开发环境合理) |
| Redis 地址 | [`config.go:88-89`](backend/gateway/internal/config/config.go:88) | `localhost:6379` | 🟢 信息 |
> **建议**
> - 生产部署时通过环境变量覆盖所有密码
> - `INTERNAL_SERVICE_TOKEN` 建议在启动时检测是否为默认值并打印警告
> - 可考虑添加 `.env.example` 注释标注哪些变量必须修改
### 3.5 Goroutine 泄漏风险
| 检查项 | 结果 |
|--------|------|
| `go func()` 调用 | 19 处 |
| 带 `defer wg.Done()` | ✅ Thinker、Subsession 均正确使用 WaitGroup |
| 带 `close(channel)` | ✅ 编排器、LLM Stream、子会话管理器均正确关闭 |
| 带 `stopCh` 机制 | ✅ Thinker (`stopCh`)、Hub (`iotStopCh`)、RuleEngine (`stopCh`) |
| 带 `context.Context` | ✅ LLM 调用均传入 context |
> **分析**goroutine 生命周期管理非常规范,未发现泄漏风险。所有 channel 在发送方关闭,所有 goroutine 有明确的退出机制。
### 3.6 资源关闭
| 检查项 | 结果 |
|--------|------|
| `defer resp.Body.Close()` | ✅ **83+ 处** — HTTP 响应体全部正确关闭 |
| `defer file.Close()` | ✅ 文件上传/下载处理全部正确关闭 |
| `defer rows.Close()` | ✅ 所有数据库查询全部正确关闭 |
| `defer store.Close()` | ✅ Memory-Service 和 AI-Core 在 main 中 defer |
> **分析**:资源管理非常严谨,无遗漏。
### 3.7 TODO/FIXME 标记
| 检查项 | 结果 |
|--------|------|
| TODO/FIXME/HACK/XXX | ✅ **0 处** — 代码库无遗留标记 |
### 3.8 Go Vet 检查
| 服务 | 结果 |
|------|------|
| gateway | ✅ 通过 |
| ai-core | ✅ 通过 |
| iot-debug-service | ✅ 通过 |
| memory-service | ✅ 通过 |
| tool-engine | ✅ 通过 |
| voice-service | ✅ 通过 |
---
## 四、前端代码质量审计
### 4.1 依赖分析
| 类别 | 数量 | 依赖 |
|------|------|------|
| 生产依赖 | 3 | react, react-dom, zustand |
| 开发依赖 | 8 | typescript, vite, tailwindcss, postcss, autoprefixer, @vitejs/plugin-react, @types/react, @types/react-dom |
> **分析**:依赖极简,仅 3 个运行时依赖,无冗余包。使用 zustand 作状态管理(轻量,~1KB),不引入 Redux 等重型方案。
### 4.2 TypeScript 配置
| 配置项 | 值 |
|--------|-----|
| `strict` | ✅ `true` |
| `noUnusedLocals` | ❌ `false` |
| `noUnusedParameters` | ❌ `false` |
| `noFallthroughCasesInSwitch` | ✅ `true` |
| `target` | ES2020 |
| `jsx` | react-jsx |
> **分析**:已启用 TypeScript 严格模式,但未启用未使用变量检查。建议将 `noUnusedLocals` 和 `noUnusedParameters` 设为 `true` 以保持代码清洁。
### 4.3 构建产物
| 项目 | 大小 |
|------|------|
| `dist/assets/` | 328 KB |
| `dist/images/` | 20 MB |
| `dist/index.html` | 4 KB |
| `dist/` 总大小 | 20 MB |
| 总文件数 | 17 |
> **分析**
> - **JS/CSS 产物仅 328KB**,非常轻量,构建优化良好。
> - **图片资源占用 20MB**,主要来自 Cyrene 角色立绘 (`Cyrene_Avatar/` 和 `ChatBackground/`)。建议:
> - 使用 WebP/AVIF 格式替代 PNG,可减少 50-70% 体积
> - 考虑按需懒加载,首屏不加载全部形态/表情
> - 使用响应式图片 (`srcset`) 按屏幕分辨率加载不同尺寸
### 4.4 控制台日志
| 类型 | 数量 | 分布 |
|------|------|------|
| `console.log` | 15 | WebSocket (6)、PWA (4)、SessionStore (1)、main.tsx (2)、Sidebar (1)、Files (1) |
| `console.error` | 17 | FilePanel (4)、sessions.ts (5)、files.ts (3)、useWebSocket.ts (2)、ImageLightbox (1)、ChatInput (1)、Sidebar (1) |
| `console.warn` | 2 | useWebSocket.ts (1)、useSpeechSynthesis.ts (1) |
> **分析**
> - 共 **34 处** console 调用,全部带有模块标签如 `[WS#]`、`[FilePanel]`、`[Sidebar]`,便于调试
> - WebSocket 相关日志最多 (10+),对于调试连接问题有价值
> - **建议**:生产构建时通过 Vite 配置自动移除 `console.log`(保留 `console.error`),或使用条件编译
---
## 五、综合评估
### 5.1 优势总结
| 维度 | 评级 | 说明 |
|------|------|------|
| 响应性能 | ⭐⭐⭐⭐⭐ | 健康检查 < 1ms50 并发仅 53ms |
| 内存效率 | ⭐⭐⭐⭐⭐ | 6 个服务合计 < 40MB RSS |
| 资源管理 | ⭐⭐⭐⭐⭐ | Body/File/Rows 正确关闭,无泄漏 |
| Goroutine 安全 | ⭐⭐⭐⭐⭐ | 全面 panic 恢复,正确 channel 关闭 |
| 日志规范 | ⭐⭐⭐⭐⭐ | 无 fmt.Println,统一 log.Printf + 标签 |
| HTTP 状态码 | ⭐⭐⭐⭐⭐ | 精确映射,统一错误格式 |
| 前端依赖 | ⭐⭐⭐⭐⭐ | 仅 3 个运行时依赖 |
| TypeScript | ⭐⭐⭐⭐ | strict 模式已启用 |
### 5.2 待改进项 (按优先级排序)
| 优先级 | 项目 | 描述 | 修复建议 |
|--------|------|------|----------|
| 🟠 P1 | 内部 Token 默认值 | `cyrene-internal-token-change-me` 是占位值 | 启动时生成随机 token 并打印,或要求环境变量非空 |
| 🟡 P2 | 前端图片优化 | 20MB 图片影响首次加载 | 转 WebP、懒加载、响应式图片 |
| 🟡 P2 | TypeScript 未使用变量检查 | `noUnusedLocals` / `noUnusedParameters` 均为 false | 设为 true,清理未使用代码 |
| 🟡 P2 | 生产构建移除 console.log | 34 处 console 调用会出现在生产构建 | Vite 配置 `drop_console: true` (保留 error) |
| 🟢 P3 | 数据库连接空闲超时 | 未设置 `SetConnMaxIdleTime` | 添加 1-2 分钟空闲超时 |
| 🟢 P3 | 系统内存压力 | 宿主机仅 540MB 可用 | 非 Cyrene 问题,建议检查其他进程 |
### 5.3 无问题项 (已验证安全)
| 检查项 | 结论 |
|--------|------|
| fmt.Println 污染 | 0 处 — 安全 |
| 未处理的 panic | 0 处 — 安全 |
| TODO/FIXME 遗留 | 0 处 — 安全 |
| goroutine 泄漏 | 0 处 — 安全 |
| HTTP Body 未关闭 | 0 处 — 安全 |
| go vet 警告 | 0 处 — 安全 |
| 未使用的依赖包 | 0 处 — 安全 |
---
## 六、结论
第6轮调试确认 Cyrene 项目在性能和代码质量方面表现出色:
1. **性能**:所有服务健康检查延迟 < 7ms,Gateway 在 50 并发下总耗时仅 53ms,具备良好的并发处理能力。
2. **内存**:6 个 Go 微服务合计仅占用约 40MB RSS,内存效率极高。
3. **代码质量**:资源管理、错误处理、goroutine 安全、日志规范均达到生产级标准。`go vet` 全部通过。
4. **前端**:依赖极简(3 个),TypeScript 严格模式已启用,构建产物 JS 部分仅 328KB。
**建议优先处理**:内部服务 Token 默认值安全加固 (P1),以及前端图片优化以改善加载时间 (P2)。
---
> **下轮预告**:第7轮可聚焦端到端集成测试、CI/CD 流水线检查、或性能调优(如图片懒加载、缓存策略)。