Agent: architect (
architect)
Confidence: 79%
Cost: $0.9663
Duration: 3m 39s
Task ID:52038643-1011-40f9-80af-9df35d15ac1e
★ Insight ─────────────────────────────────────
這份分析揭示了幾個重要的架構模式教訓:
「全量讀取尾部資料」是 append-only JSONL 系統最常見的 antipattern。四個不同的模組(agent-tuner, audit-chain, search-index, explorer)都犯了同樣的錯——全量
readFile()+split('\n')+slice(-N)。一個通用的tailJsonl()工具可以一次解決四個問題。這就是為什麼架構分析要尋找「共同模式」而非逐個修補。EventBus 的 event payload 設計決定了下游效率的上限。
memory:updated事件只攜帶{ chatId, type },缺少index資訊,逼迫 search-index 做全量重索引。這是典型的「事件設計太粗糙導致消費者過度補償」問題。在設計 EventBus 事件時,多帶一個 field 的成本趨近於零,但缺少它的代價是 O(N) vs O(1)。同步 I/O 在 Node.js 中的嚴重度常被低估。
readFileSync在 1.2MB 時阻塞 50-100ms 看似不多,但在 Telegram bot 的 concurrent polling 架構中,這 100ms 意味著所有用戶的所有訊息完全凍結。Node.js 的單執行緒模型下,同步 I/O 的真實成本 = 阻塞時間 × 同時等待的請求數。─────────────────────────────────────────────────
報告摘要
已完成全部 9 個瓶頸的深入分析。重新評估後的優先級排序:
確認修復(6 個)
| 方案 | 瓶頸 | 核心改動 |
|---|---|---|
| B (P0) | search-index 全量重索引 | event payload 加 index,handler 精準 upsert |
| C (P0) | explorer.ts 同步 I/O | readFileSync → readFile (async) |
| A (P1) | agent-tuner / audit-chain / search-index JSONL 全量讀取 | 新增 tailJsonl() 工具,從尾部讀取 |
| D (P1) | search-index Maps 無上限 | 加入 enforceLimit(5000) |
決定不修(3 個)
| 瓶頸 | 理由 |
|---|---|
| chat-memory cache (#5) | 單 chat 場景,洩漏量 ~0 |
| narrative slice (#8) | 有 archive 機制控制檔案大小 |
| stdout += (#9) | non-streaming 路徑 + 10MB cap + V8 rope string |
關鍵架構決策
- 不做 CappedMap 通用工具 — search-index 的三個 Map 互相耦合,通用化是過度設計
- tailJsonl 是最高槓桿改動 — 一個工具同時解決 4 個模組的問題
- Phase 1 兩個 P0 任務可完全並行,Phase 2 依賴 tailJsonl 工具先完成
報告已存入 soul/agent-reports/architect/2026-02-28-perf-bottleneck-analysis.md。